//============================================================================================
/**
 * @file	pkthln_throw.c
 * @brief	玉投げ
 * @author	Nozomu Saito
 *
 * モジュール名：PE_THROW_
 */
//============================================================================================
#include "../../pokethlon.h"
#include "../../pkthln_poke_act.h"

#include "pkthln_throw.h"
#include "pkthln_throw_local.h"
#include "../../pkthln_obj_common.h"
#include "../../poke_clact.h"
#include "../pkthln_clact.h"
#include "../pkthln_act_def.h"

#include "system/snd_tool.h"
#include "system/wipe.h"
#include "system/render_oam.h"
#include "system/fontproc.h"
#include "gflib/touchpanel.h"

#include "../../pkthln_comm_pack.h"
#include "../../poke_clact_move.h"

#include "../event_se_def.h"

#include "system/arc_util.h"

#include "throw_comm.h"
#include "throw_obj_pri.h"

#include "../../cmn_res.h"

#include "pkthln_throw_sub.h"

#include "throw_ai.h"

#include "throw_calc.h"

//成績作成用
#include "system/msgdata_util.h"
#include "msgdata/msg.naix"
#include "msgdata/msg_pokethlon.h"

#include "../pkthln_evt_info.naix"
#include "pkthev_throw.naix"
#include "communication/wm_icon.h"

// 構造体が想定のサイズとなっているかチェック
#ifdef PM_DEBUG
#ifdef _NITRO
SDK_COMPILER_ASSERT(sizeof(THROW_PARENT_DATA) == 36);
#endif
extern DEBUG_PKTHLN_WORK DebugPkthlnWk;
#endif		//PM_DEBUG


//デバッグ機能
#ifdef PM_DEBUG
///#define DEBUG_MIN_TIME			//デバッグ短縮時間
#endif

#define THROW_HEAP_SIZE		(0x40000)

#define THROW_EVENT_POKE_NUM	(ENTRY_MAX*(ENTRY_MEMBER_NUM_MAX-1))	//自分３体は数に入れない
#define MAIN_ACT_MAX	( ( 1+1+1+2+(THROW_EVENT_POKE_NUM*9) ) + 1 + 2*(ENTRY_MEMBER_NUM_MAX-1) )
//↑カウントダウン+ラストカウント+ニューレコード+タイム2+(混乱+汗+ボール+ボール影+粉砕+ポイントゲット+ポケ+影+マーカ)*ポケ数+時計1+(旗+得点取得)3
#define SUB_ACT_MAX	(7*ENTRY_MAX+1)
//↑(混乱+汗+ポケグラ+玉+玉影+粉砕+ペン)*自ポケ数+得点取得

#define ACT_MAX		(MAIN_ACT_MAX + SUB_ACT_MAX)

#define THROW_OBJ_MAIN_PAL_NUM	(3)		//競技メインパレット3
#define THROW_OBJ_CMN_PAL_NUM	(2)		//競技上下共通パレット2

#define THROW_SUB_OBJ_PAL_NUM	(THROW_OBJ_CMN_PAL_NUM+THROW_OBJ_SUB_PAL_NUM+1)
//↑競技共通パレット+サブパレット+フォント1
#define THROW_MAIN_OBJ_PAL_NUM	(1+THROW_OBJ_CMN_PAL_NUM+THROW_OBJ_MAIN_PAL_NUM+THROW_EVENT_POKE_NUM)
//↑共通リソース1+競技共通パレット+メインパレット+自分以外ポケ9

#define THROW_EVENT_OBJ_NUM	( ACT_MAX )

#define THROW_EVENT_PAL_NUM	( THROW_SUB_OBJ_PAL_NUM + THROW_MAIN_OBJ_PAL_NUM )

#define PCLACT_TCB_PRIORITY	(0)
#define OBJ_BG_PRI	(3)			//OBJのBGプライオリティ

#define POINT_MAX	(999)	//最大得点

//ＢＭＰ関連
#define	REC_FONT_PAL	(15)
#define	NAME_FONT_PAL	(REC_FONT_PAL)
#define WIN_CGX_BASE	(1)
#define WIN_REC_CGX	(WIN_CGX_BASE)
#define REC_BG	(GF_BGL_FRAME3_M)
#define NAME_BG	(GF_BGL_FRAME0_M)

#define WIN_NAME1_PX		(24)
#define WIN_NAME1_PY		(2)
#define WIN_NAME2_PX		(13)
#define WIN_NAME2_PY		(2)
#define WIN_NAME3_PX		(2)
#define WIN_NAME3_PY		(2)
#define WIN_NAME_SX		(8)
#define WIN_NAME_SY		(2)
#define WIN_NAME_SIZE	( WIN_NAME_SX * WIN_NAME_SY )
#define WIN_NAME1_CGX	(1)
#define WIN_NAME2_CGX	(WIN_NAME1_CGX+WIN_NAME_SIZE)
#define WIN_NAME3_CGX	(WIN_NAME2_CGX+WIN_NAME_SIZE)
#define	COL_N_WHITE	( GF_PRINTCOLOR_MAKE( 15, 14, 0 ) )		// フォントカラー：白


#define BALL_NUM_MAX	(ENTRY_MAX*ENTRY_MEMBER_NUM_MAX)
#ifdef DEBUG_MIN_TIME
#define GAME_TIME		(30)		//デバッグ短縮ゲーム時間
#else
#define GAME_TIME		(60*30)		//ゲーム時間60秒
#endif


#define POKE_TOUCH_RANGE	(4*FX32_ONE)
#define BALL_RANGE	(2)
#define POKE_RANGE	(1)

#define BREAK_WAIT	(8)
#define STOP_TIME_MIN	(40)
#define FATIGUE_ST_VAL	(100)
#define TOUCH_TIME_MAX	(30.0)
#define CMN_DAMAGE	(30)
#define TIME_DIGI_MAX	(2)


#define SORT_NUM_MAX	(BALL_NUM_MAX)


//固定座標とか
#define WATCH_X	(1*8*FX32_ONE)
#define WATCH_Y	(8*FX32_ONE)
#define FLAG1_X	(184*FX32_ONE)
#define FLAG1_Y	(24*FX32_ONE)
#define FLAG2_X	(96*FX32_ONE)
#define FLAG2_Y	(24*FX32_ONE)
#define FLAG3_X	(8*FX32_ONE)
#define FLAG3_Y	(24*FX32_ONE)

#define STEF_LRG_Y_OFS	(40)
#define STEF_SML_Y_OFS	(25)

#define TIMER_ACT_POS_X	(3*8*FX32_ONE)
#define TIMER_ACT_POS_Y	(8*FX32_ONE)
#define TIMER_ACT_W	(16)		//時間数字ドット幅


#define POINT_ANM_OFS	(6)		//メイン画面ポイントアニメオフセット

#define SORT_BUF_SIZE	(40)
//Nitro関数MATH_QSortを使用する際のソート作業領域
//必要サイズは、マニュアルによると (Log2(num)+1) * 8 byte
//今回ソートする数はSORT_NUM_MAX　=　12 なので
//Log2(12)+1 * 8 < Log2(16)+1 *8 = (4+1)*8 = 40 byte 用意しとく

typedef struct THROW_PARAM_tag
{
	int Technique2[5];
	int Power[5];
	int Technique[5];
	int Damage[5];
}THROW_PARAM;

typedef struct PKTHLN_THROW_tag
{
	GF_BGL_INI *bgl;
	GF_BGL_BMPWIN	Win;			// BMPウィンドウデータ
	GF_BGL_BMPWIN	NameWin[ENTRY_MEMBER_NUM_MAX-1];			// BMPウィンドウデータ
	int HeapID;
	//アクター
	PKTHLN_CLACT_CNT_PTR ActCntPtr;
	//時計
	PKTHLN_ACT_PTR	WatchActPtr;
	//時間
	CLACT_WORK_PTR	TimeActPtr[TIME_DIGI_MAX];
	//旗
	PKTHLN_ACT_PTR	FlagActPtr[ENTRY_MEMBER_NUM_MAX-1];
	//ポイント取得
	PKTHLN_ACT_PTR	PointActPtr[ENTRY_MAX];
	//自分以外の汗
	PKTHLN_ACT_PTR SweatActPtr[THROW_EVENT_POKE_NUM];
	//他ポケ
	POKE_ACT_PTR 	PokeActPtr[THROW_EVENT_POKE_NUM];
	//ボール
	THROW_BALL Ball[BALL_NUM_MAX];
	THROW_POKE Poke[THROW_EVENT_POKE_NUM_ALL];

	//ソートバッファ
	u8 *SortBuf;

	TP_STATE	TpState[ENTRY_MEMBER_NUM_MAX];		//親が使う
	u8 HoldPoke[ENTRY_MEMBER_NUM_MAX];			//親が使う

	u8 EndFlg;
	u8 StartCount;
	u8 LclTchSt;
	u8 HitEffIdx;

	CMN_RES_CNT_PTR	CmnResCntPtr;
	POKE_ACT_CNT_PTR PokeActCntPtr;

	THROW_AI_CONT_PTR AICntPtr;
	THROW_SUB_CNT_PTR SubDispCntPtr;

	u8 HitEff;
	u8 HitEffY;
	u16 HitEffX;

	u16 CommTime;			//通信する時間データ
	u8 TouchTime;
	u8 dummy;

	//↓ＳＥ用
	u8 BallSizeTemp[ENTRY_MAX];
	u8 ThrowSeFlg[ENTRY_MAX];
	u8 dummy_se[2];

}PKTHLN_THROW;

typedef struct SORT_WORK_tag
{
	u16 NetID;
	u16 Idx;
	fx32 Y;
}SORT_WORK;

static void SetVramBank(void);
static void BgInit(GF_BGL_INI * ini);
static void SetGraphic(PKTHLN_THROW_PTR ptr, const u8 inNetID);
static void SetObj( PKTHLN_CLACT_CNT_PTR pActCntPtr);
static void SetAct( PKTHLN_THROW_PTR ptr, PKTHLN_CLACT_CNT_PTR pActCntPtr, const u8 inNetID);

static BOOL THROW_Func_Phase0(PKTHLN_PTR work, u8 *seq);
static BOOL THROW_Func_Phase1(PKTHLN_PTR work, u8 *seq);

static void SetCommInfo(PKTHLN_THROW_PTR ptr, THROW_PARENT_DATA *parent);
static void CommMain(PKTHLN_PTR work);
static BOOL ControlMain(PKTHLN_PTR work);
static void SetDraw(PKTHLN_PTR work);

static void MovePoke(PKTHLN_PTR work);
static void MoveBall(PKTHLN_PTR work);
static void HitCheckPoke(PKTHLN_PTR work, PKTHLN_THROW_PTR ptr);
static void HitCheckBall(PKTHLN_THROW_PTR ptr);

static u8 CheckPokeTouch(	PKTHLN_THROW_PTR ptr, const u8 inNetID,
							const u16 inX, const u16 inY, VecFx32 *outVec);
static void SetPokeParam(	PKTHLN_PTR work, const THROW_PARAM *inData,
							const u8 inNetID, const u8 inIdx, THROW_POKE *outPoke);

static void CreateBmpWin( PKTHLN_THROW_PTR ptr );
static void WriteName(PKTHLN_THROW_PTR ptr, PKTHLN_PTR work);
static void SetRecordStr(PKTHLN_THROW_PTR ptr, const int inRecord);
static void DispTime(PKTHLN_THROW_PTR ptr, const u16 inTime);

static void RecCallBack(PKTHLN_PTR work);

static s32 CompFunc(void *elem1, void *elem2);
static void SortObj(PKTHLN_THROW_PTR ptr, const u8 inNetID);

PKTHLN_FUNC ThrowFuncTbl[] = {
	THROW_Func_Phase0,
	THROW_Func_Phase1,
};

enum {
	THROW_SEQ_PHASE0,
	THROW_SEQ_PHASE1,
};

#ifdef PM_DEBUG
static u8 debug_print = 0;
#endif

static const int MainPokePosX[] = {
	246,248,249,199,175,150,82,63,37
};

static const int MainPokePosY[] = {
	170,130,100,70,70,70,100,130,170
};

//Y座標が同じときのボールプライオリティ
static const u8 DefBallPri[ENTRY_MEMBER_NUM_MAX][ENTRY_MAX*ENTRY_MEMBER_NUM_MAX] = {
	{ 11,10,9,8,7,6,3,4,5,2,1,0 },
	{ 2,1,0,11,10,9,8,7,6,3,4,5 },
	{ 3,4,5,2,1,0,11,10,9,8,7,6 },
	{ 8,7,6,3,4,5,2,1,0,11,10,9 },
};

//他ポケのプライオリティ順
static const u8 PokePriOfs[THROW_EVENT_POKE_NUM] = {
	0,2,4,6,7,8,5,3,1
};

#ifdef PM_DEBUG
static VecFx32 target_pos = {60*FX32_ONE,0,40*FX32_ONE};
static VecFx32 start_pos = {24*FX32_ONE,0,60*FX32_ONE};
static VecFx32 ball_vec = {24*FX32_ONE,0,60*FX32_ONE};
static u8 t_poke_no = 3;
static u8 poke_no = 0;
static u8 shot_count = 0;
static u8 b_frame = 0;

typedef struct DBG_THROW_WORK_tag
{
	u16 main_start;
	u16 test_sync;
}DBG_THROW_WORK;

static DBG_THROW_WORK dbg_w = {0,0};
#endif


//--------------------------------------------------------------------------------------------
/**
 * 初期化関数
 *
 * @param	work		ポケスロンワークポインタ
 * @param	*pParam		パラメータ
 *
 * @return	TRUE
 */
//--------------------------------------------------------------------------------------------
PTH_RC PE_THROW_InitFunc(PKTHLN_PTR work, void *pParam)
{
	PKTHLN_THROW_PTR ptr = PTFrame_GetEventWorkPtr(work);
	u8 seq = PTFrame_GetSubSeq(work);
	switch(seq){
	case 0:
		{
			int heap_id;
			sys_CreateHeap( HEAPID_POKETHLON, HEAPID_PT_THROW, THROW_HEAP_SIZE );
			heap_id = HEAPID_PT_THROW;

			sys_VBlankFuncChange( NULL, NULL );	// VBlankセット
			sys_HBlankIntrSet( NULL,NULL );		// HBlankセット

			GF_Disp_GX_VisibleControlInit();
			GF_Disp_GXS_VisibleControlInit();
			GX_SetVisiblePlane( 0 );
			GXS_SetVisiblePlane( 0 );

			//VRAMバンク割り当て
			SetVramBank();
			//アプリケーションメモリー
			ptr = PTFrame_AllocEventWork(work, sizeof(PKTHLN_THROW));
			MI_CpuClear8( ptr, sizeof(PKTHLN_THROW));
			//ソートバッファアロック
			{
				ptr->SortBuf = sys_AllocMemory(heap_id, SORT_BUF_SIZE);
				MI_CpuClear8( ptr->SortBuf, SORT_BUF_SIZE);
			}
			//BGLアロケーション
			ptr->bgl = GF_BGL_BglIniAlloc(heap_id);

			//レコード表示ＢＧのセット
			PTFrame_SetRecBGMask(work, GX_PLANEMASK_BG3);

			{
				CHAR_MANAGER_MAKE cm;
				cm.CharDataNum = THROW_EVENT_OBJ_NUM;
				cm.VramTransAreaMain = 256*1024;
				cm.VramTransAreaSub = 16*1024;
				cm.heap = PTFrame_GetHeapID(work);

				//キャラ・パレットマネージャ初期化
				PKTHLN_OBJ_COMMON_InitCharPlttManager(	&cm,
														THROW_EVENT_PAL_NUM,
														heap_id,
														GX_OBJVRAMMODE_CHAR_1D_256K,
														GX_OBJVRAMMODE_CHAR_1D_256K);
			}

			// OAMマネージャーの初期化
			NNS_G2dInitOamManagerModule();

			// 共有OAMマネージャ作成
			// レンダラ用OAMマネージャ作成
			// ここで作成したOAMマネージャをみんなで共有する
			REND_OAMInit(
					0, 126,		// メイン画面OAM管理領域
					0, 32,		// メイン画面アフィン管理領域
					0, 126,		// サブ画面OAM管理領域
					0, 32,		// サブ画面アフィン管理領域
					heap_id);
			ptr->HeapID = heap_id;
		}

		//タッチフォントロード
		FontProc_LoadFont(FONT_TOUCH, ptr->HeapID);

		BgInit(ptr->bgl);

		//BMP
		CreateBmpWin(ptr);
		WriteName(ptr, work);

		//上画面をメインにする
		sys.disp3DSW = DISP_3D_TO_MAIN;
		GF_Disp_DispSelect();

		//次のシーケンスへ
		PTFrame_IncSubSeq(work);

		break;
	case 1:
		ptr->SubDispCntPtr = ThrowSub_Init( ptr->HeapID, ptr->bgl, work);
		ptr->AICntPtr = ThrowAI_Init(ptr->HeapID,
				ENTRY_MEMBER_NUM_MAX-PTFrame_GetPlayerNum(work), PTFrame_GetGameType(work));

		//次のシーケンスへ
		PTFrame_IncSubSeq(work);
		break;
	case 2:
		{
			int i;
			CLACT_WORK_PTR act_ptr;
			PKTHLN_ACT_SETUP_PRM param = {
				ACT_MAX,3,{3,3,3,3}
			};
			ptr->ActCntPtr = PkthlnClAct_Init(ptr->HeapID, &param);

			//上下画面幅設定
			PkthlnClAct_SetDispDistance(ptr->ActCntPtr,
										0, 0,
										0, SUB_DISP_DISTANCE );
			PkthlnClAct_SetResObjCode(ptr->ActCntPtr, 0, RES_CODE_THROW_CMN);
			PkthlnClAct_SetResObjCode(ptr->ActCntPtr, 1, RES_CODE_THROW_SUB);
			PkthlnClAct_SetResObjCode(ptr->ActCntPtr, 2, RES_CODE_THROW_MAIN);

			//メインサブ共通セット後、メインセット
			SetObj(ptr->ActCntPtr);
			//サブ
			ThrowSub_SetObj( ptr->SubDispCntPtr, ptr->ActCntPtr );
			//トランス
			PkthlnClAct_Trans(ptr->ActCntPtr);

			//上下画面共通で使用するパレットがあるので、パレット位置を合わせるため共通リソースを後でセット
			ptr->CmnResCntPtr = CmnRes_Init( ptr->HeapID,
				CMN_RES_ALL_BIT|CMN_RES_F2X2_BIT|CMN_RES_PEN_S_BIT, NNS_G2D_VRAM_TYPE_2DMAIN );
			//ポケモンアクター
			ptr->PokeActCntPtr = PokeAct_Init( ptr->HeapID, THROW_EVENT_POKE_NUM, PRI_POKE,
									  ptr->CmnResCntPtr, PkthlnClAct_GetClActSetAdr(ptr->ActCntPtr) );

			//カウントダウンアクター
			{
				CLACT_WORK_PTR	*act_adr;
				act_adr = PTFrame_SetCountDown( work, 0, ptr->CmnResCntPtr, ptr->ActCntPtr );
				//プライオリティセット
				CLACT_DrawPriorityChg( *act_adr, PRI_COUNT );
			}

			//メイン画面ＯＢＪ
			SetAct( ptr, ptr->ActCntPtr, PTFrameGetCurrentID(work));
		}
		//次のシーケンスへ
		PTFrame_IncSubSeq(work);
		break;
	case 3:
		{
			u8 net_id;
			u8 base_idx;
			int i;
			MONS_INFO info[THROW_EVENT_POKE_NUM_ALL];
			PCLACT_SET_PARAM param;

			net_id = PTFrameGetCurrentID(work);
			//右隣のチームのインデックス開始は((net_id+1)*3)%THROW_EVENT_POKE_NUM_ALL
			base_idx = ((net_id+1)*3)%THROW_EVENT_POKE_NUM_ALL;
			//↓ここが、プレーヤによって違ってくる
			for(i=0;i<THROW_EVENT_POKE_NUM_ALL;i++){
				u8 poke_idx;
				//ポケモンインデックス算出
				poke_idx = (base_idx+i)%THROW_EVENT_POKE_NUM_ALL;
				PTFrame_SetMonsInfo(work, poke_idx/ENTRY_MAX, poke_idx%ENTRY_MAX, &info[i]);

				param.ShadowPos[i] =
					PTFrame_GetPokeShdwPosType(PTFrame_GetPkthlnParam(work, poke_idx/ENTRY_MAX, poke_idx%ENTRY_MAX));
			}
			//サブ画面ポケモンセット(自分のポケはインフォデータの末尾3つに存在する)
			ThrowSub_SetPokeAct( ptr->SubDispCntPtr, ptr->ActCntPtr, &info[THROW_EVENT_POKE_NUM] );
			//自ポケの混乱エフェクト位置をセット
			for(i=0;i<ENTRY_MAX;i++){
				VecFx32 vec = {0,0,0};
				int height;
				const MONS_INFO *my_info;
				my_info = &info[THROW_EVENT_POKE_NUM+i];
				height = PokeHeightGet(my_info->MonsNo, my_info->Sex , PARA_BACK, my_info->Form ,my_info->PsnlRnd);
				vec.x = ( MY_POKE_BASE_X + (MY_POKE_MARGINE_X*i) ) * FX32_ONE;
				vec.y = ( MY_POKE_BASE_Y + height ) * FX32_ONE;
				vec.y -= SWEAT_OFS;
				PkthlnClAct_SetPos(ptr->Poke[net_id*ENTRY_MAX+i].PanicActPtr, &vec);
			}

			param.Quick = 0;
			param.BGPriority = OBJ_BG_PRI;
			param.Trans = 0;
			param.ResVramType = NNS_G2D_VRAM_TYPE_2DMAIN;
			param.DrawArea = NNS_G2D_VRAM_TYPE_2DMAIN;

			PokeAct_SetPokeActor(	ptr->PokeActCntPtr, THROW_EVENT_POKE_NUM,
									info, &param,
									PCLACT_TCB_PRIORITY,
									0 );

			//サブ画面ＯＢＪプライオリティセット
///			ThrowSub_SetPriority( ptr->SubDispCntPtr, PTFrameGetCurrentID(work));

		}
		//次のシーケンスへ
		PTFrame_IncSubSeq(work);
		break;
	case 4:
		if ( PokeAct_CheckActSetTask(ptr->PokeActCntPtr) ){
			int net_id;
			u8 base_idx;
			int i;
			const POKE_DIR poke_dir[3] = {POKE_DIR_LEFT,POKE_DIR_DOWN,POKE_DIR_RIGHT};

			PTFrame_SetDefaultVBlankFunc(ptr->bgl);	// VBlankセット
			//描画を許可
			PTFrame_SetDraw(work, TRUE);

			net_id = PTFrameGetCurrentID(work);
			//右隣のチームのインデックス開始は((net_id+1)*3)%THROW_EVENT_POKE_NUM_ALL
			base_idx = ((net_id+1)*3)%THROW_EVENT_POKE_NUM_ALL;

			//ポケセルアクター
			for (i=0;i<THROW_EVENT_POKE_NUM;i++){
				POKE_ACT_PTR poke_ptr;
				ptr->PokeActPtr[i] = PokeAct_GetPokeActPtr(ptr->PokeActCntPtr, i);
				poke_ptr = ptr->PokeActPtr[i];
				PokeAct_DispCnt(poke_ptr, 1);	//表示

				//ポケモン初期位置
				{
					//テーブルで位置決定
					u8 poke_idx;
					int sx,sy;
					int range;

					//ポケモンインデックス算出
					poke_idx = (base_idx+i)%THROW_EVENT_POKE_NUM_ALL;
					//影の位置
					sx = MainPokePosX[i];
					sy = MainPokePosY[i];

					//向きセット
					PokeAct_SetDir(poke_ptr, poke_dir[i/ENTRY_MAX]);
					//アクター位置セット
					PokeAct_SetPosShadow(poke_ptr, sx, sy);

					//エフェクト位置を決定
					{
						VecFx32 vec = {0,0,0};
						PCLACT_PTR  act_ptr = PokeAct_GetPclActPtr(poke_ptr);
						if (PCLACT_GetMonsInfo(act_ptr)->CellType){		//大きいポケ
							vec.x = sx * FX32_ONE;
							vec.y = (sy-STEF_LRG_Y_OFS) * FX32_ONE;
						}else{		//小さいポケ
							vec.x = sx * FX32_ONE;
							vec.y = (sy-STEF_SML_Y_OFS) * FX32_ONE;
						}
						//座標セット
						PkthlnClAct_SetPos(ptr->Poke[poke_idx].PanicActPtr, &vec);	//混乱
						PkthlnClAct_SetPos(ptr->SweatActPtr[i], &vec);//汗
					}

					//ポケモンプライオリティ
					PokeAct_SetPriority(poke_ptr, PRI_POKE+PokePriOfs[i]);
				} //ポケモン初期位置
			}	//end for

			{
				THROW_PARAM data;
				int i;
				ArchiveDataLoad(&data, ARC_PKTHEVT_PARAM, NARC_pkthln_evt_info_throw_bin);
				for (i=0;i<5;i++){
					OS_Printf("%d,%d,%d,%d\n",
							data.Technique2[i],data.Power[i],data.Technique[i],data.Damage[i]);
				}

				//ゲーム時間セット
				ptr->CommTime = GAME_TIME;

				for(i=0;i<ENTRY_MEMBER_NUM_MAX;i++){
					int j;
					//親の判定データ初期化
					ptr->HoldPoke[i] = THROW_EVENT_POKE_NUM_ALL;
					//パラメータ格納

					for(j=0;j<ENTRY_MAX;j++){
						THROW_POKE *throw_poke;
						throw_poke = &ptr->Poke[i*ENTRY_MAX+j];
						SetPokeParam(work, &data, i, j, throw_poke);
						if (PTFrameGetCurrentID(work) == COMM_PARENT_ID){
							//AI用にポケモンデータをセットアップ
							ThrowAI_SetupInfo( ptr->AICntPtr, i*ENTRY_MAX+j, throw_poke, &ptr->Ball[i*ENTRY_MAX+j] );
						}
					}
				}
				//親のとき、初回送信データを作成
				if (PTFrameGetCurrentID(work) == COMM_PARENT_ID){
					COMM_EVENT_COMMON_DATA *data;
					data = PTFrame_GetEvtComCmnData(work);
					SetCommInfo(ptr,
							PKTHLN_CommPack_GetData(&data->SendShareData));
				}
			}

			//ペン表示
			ThrowSub_SetPen( ptr->SubDispCntPtr, ptr->ActCntPtr,  ptr->CmnResCntPtr	);

			SetGraphic(ptr, PTFrameGetCurrentID(work));

			//ＯＢＪの表示
			GF_Disp_GX_VisibleControl( GX_PLANEMASK_OBJ, VISIBLE_ON );		// MAIN DISP OBJ ON
			GF_Disp_GXS_VisibleControl( GX_PLANEMASK_OBJ, VISIBLE_ON );		// SUB DISP OBJ ON

			//通信アイコン
			WirelessIconEasyPokethlon( NNS_G2D_VRAM_TYPE_2DMAIN );

			//フェードイン
			WIPE_SYS_Start(	WIPE_PATTERN_FSAM, WIPE_TYPE_SHUTTERIN_DOWN,
					WIPE_TYPE_SHUTTERIN_DOWN, WIPE_FADE_BLACK,
					WIPE_DEF_DIV, WIPE_DEF_SYNC, ptr->HeapID );
			//次のシーケンスへ
			PTFrame_IncSubSeq(work);
		}
		break;


	case 5:
		//フェードイン待ち
		if( WIPE_SYS_EndCheck() ){
			//初期化終了
			sys_PrintHeapFreeSize( ptr->HeapID );
			GF_ASSERT(sys_CheckHeapSafe( HEAPID_POKETHLON));
			return PTH_RC_END;
		}
		break;
	}
	return PTH_RC_LOOP;
}
//--------------------------------------------------------------------------------------------
/**
 * 描画関数
 *
 * @param	work		ポケスロンワークポインタ
 * @param	*pParam		パラメータ
 *
 * @return	TRUE
 */
//--------------------------------------------------------------------------------------------
BOOL PE_THROW_DrawFunc(PKTHLN_PTR work, void *pParam)
{
	PKTHLN_THROW_PTR ptr = PTFrame_GetEventWorkPtr(work);

	ThrowSub_DispShakeMain(ptr->SubDispCntPtr);		//画面揺らし実行関数

	PkthlnClAct_Draw(ptr->ActCntPtr);
	return TRUE;
}

//--------------------------------------------------------------------------------------------
/**
 * 競技結果計算関数
 *
 * @param	work		ポケスロンワークポインタ
 * @param	*pParam		パラメータ
 *
 * @return	TRUE
 */
//--------------------------------------------------------------------------------------------
BOOL PE_THROW_ResultFunc(PKTHLN_PTR work, void *pParam)
{
	int i,j;
	RSLT_PTR result_ptr;

	OS_Printf("競技結果データ作成\n");

	result_ptr = PTFrame_GetResultPtr(work);
	RSLT_Setup( result_ptr );

	for( i=0;i<ENTRY_MEMBER_NUM_MAX;i++ ){
		int rec;
		rec = PTFrame_GetEvtResult(work, i);
		RSLT_SetResult(	work, result_ptr,
							i, rec,
							0, 3, msg_pkthln_rs_K9 );
	}

	//ソート
	RSLT_Sort(result_ptr, SORT_REC_LARGE);
	//得点セット
	PTC_CalcPoint(result_ptr, PKTHLN_EVT_THROW);

	//総得点に加算
	RSLT_AddTotalScore(result_ptr);

	//競技得点セット
	RSLT_SetEvtScore(result_ptr, PKTHLN_EVT_THROW);

	return TRUE;
}

//--------------------------------------------------------------------------------------------
/**
 * 終了関数
 *
 * @param	work		ポケスロンワークポインタ
 * @param	*pParam		パラメータ
 *
 * @return	TRUE
 */
//--------------------------------------------------------------------------------------------
BOOL PE_THROW_EndFunc(PKTHLN_PTR work, void *pParam)
{
	int i;
	PKTHLN_THROW_PTR ptr = PTFrame_GetEventWorkPtr(work);

	// 通信アイコン撤去
	WirelessIconEasyEnd();

	//共有データクリア
	PTFrame_ClearEvtShareDataPtr(work);

	//スクリーンアーカイブ解放
///	sys_FreeMemoryEz(ptr->MainBgArc);
	//BG削除
	GF_BGL_BGControlExit(ptr->bgl, GF_BGL_FRAME0_M );
	GF_BGL_BGControlExit(ptr->bgl, GF_BGL_FRAME1_M );
	GF_BGL_BGControlExit(ptr->bgl, GF_BGL_FRAME3_M );
	GF_BGL_BGControlExit(ptr->bgl, GF_BGL_FRAME0_S );
	GF_BGL_BGControlExit(ptr->bgl, GF_BGL_FRAME1_S );
	GF_BGL_BGControlExit(ptr->bgl, GF_BGL_FRAME2_S );
	GF_BGL_BGControlExit(ptr->bgl, GF_BGL_FRAME3_S );

	//BMP
	GF_BGL_BmpWinDel( &ptr->Win );
	for(i=0;i<ENTRY_MEMBER_NUM_MAX-1;i++){
		GF_BGL_BmpWinDel( &ptr->NameWin[i] );
	}

	//BGL解放
	sys_FreeMemoryEz(ptr->bgl);

	//アクター解放
	PkthlnClAct_Free(ptr->ActCntPtr);

	//ポケアクターコントローラ解放
	PokeAct_Free(ptr->PokeActCntPtr);
	//共通リソースコントローラ解放
	CmnRes_Free(ptr->CmnResCntPtr);

	//OAMレンダラー破棄
	REND_OAM_Delete();

	DeleteCharManager();
	DeletePlttManager();

	//AIコントローラー解放
	ThrowAI_End(ptr->AICntPtr);

	//サブ画面コントローラー解放
	ThrowSub_Free(ptr->SubDispCntPtr);

	//タッチフォントアンロード
	FontProc_UnloadFont(FONT_TOUCH);

	sys_VBlankFuncChange( NULL, NULL );	// VBlankセット
	sys_HBlankIntrSet( NULL,NULL );		// HBlankセット

	//ソートバッファ解放
	sys_FreeMemoryEz(ptr->SortBuf);

	//イベントワーク解放
	PTFrame_FreeEventWork(work);

	// 上下画面を元に戻しておく
	sys.disp3DSW = DISP_3D_TO_MAIN;
	GF_Disp_DispSelect();

	//特殊効果オフ
	G2_BlendNone();
	//ヒープ解放
	sys_DeleteHeap( HEAPID_PT_THROW );

	return TRUE;
}

//--------------------------------------------------------------------------------------------
/**
 * VRAM設定		ポケスロンでは、ポケモン表示だけで0x30000必要となる。
 * VRAM_AB(0x40000)でないとはいらん
 *
 * @param	none
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void SetVramBank(void)
{
	GF_BGL_DISPVRAM tbl = {
		GX_VRAM_BG_64_E,				// メイン2DエンジンのBG
		GX_VRAM_BGEXTPLTT_NONE,			// メイン2DエンジンのBG拡張パレット

		GX_VRAM_SUB_BG_128_C,			// サブ2DエンジンのBG
		GX_VRAM_SUB_BGEXTPLTT_NONE,		// サブ2DエンジンのBG拡張パレット

		GX_VRAM_OBJ_256_AB,				// メイン2DエンジンのOBJ
		GX_VRAM_OBJEXTPLTT_NONE,		// メイン2DエンジンのOBJ拡張パレット

		GX_VRAM_SUB_OBJ_16_I,			// サブ2DエンジンのOBJ
		GX_VRAM_SUB_OBJEXTPLTT_NONE,	// サブ2DエンジンのOBJ拡張パレット

		GX_VRAM_TEX_NONE,				// テクスチャイメージスロット
		GX_VRAM_TEXPLTT_NONE			// テクスチャパレットスロット
	};
	GF_Disp_SetBank( &tbl );
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	BG初期化
 * @param	*ini		BGL
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void BgInit(GF_BGL_INI * ini)
{
	{	/* BG SYSTEM */
  	  GF_BGL_SYS_HEADER BGsys_data = {
    	  GX_DISPMODE_GRAPHICS, GX_BGMODE_0, GX_BGMODE_0, GX_BG0_AS_2D,
    	};
  	  GF_BGL_InitBG( &BGsys_data );
  	}

  	//メイン
  	{	/* MAIN DISP BG0 */								//テキスト
    	GF_BGL_BGCNT_HEADER MBg0_Data = {
	      0, 0, 0x800, 0,
    	  GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
		  GX_BG_SCRBASE_0xe000, GX_BG_CHARBASE_0x08000,
		  GX_BG_EXTPLTT_01, 2, 0, 0, FALSE
   	 };
   	 GF_BGL_BGControlSet( ini, GF_BGL_FRAME0_M, &MBg0_Data, GF_BGL_MODE_TEXT );
   	 GF_BGL_ScrClear( ini, GF_BGL_FRAME0_M );
 	}

	{	/* MAIN DISP BG1 */
  	  GF_BGL_BGCNT_HEADER MBg1_Data = {					//背景面
    	  0, 0, 0x800, 0,
   	 	  GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
		  GX_BG_SCRBASE_0xd800, GX_BG_CHARBASE_0x00000,
		  GX_BG_EXTPLTT_01, 3, 0, 0, FALSE
   	 };
   	 GF_BGL_BGControlSet( ini, GF_BGL_FRAME1_M, &MBg1_Data, GF_BGL_MODE_TEXT );
   	 GF_BGL_ScrClear( ini, GF_BGL_FRAME1_M );
	}

	{	/* MAIN DISP BG3 */								//レコード
    	GF_BGL_BGCNT_HEADER MBg3_Data = {
	      0, 0, 0x800, 0,
    	  GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
		  GX_BG_SCRBASE_0xd000, GX_BG_CHARBASE_0x04000,
		  GX_BG_EXTPLTT_01, 0, 0, 0, FALSE
   	 };
   	 GF_BGL_BGControlSet( ini, GF_BGL_FRAME3_M, &MBg3_Data, GF_BGL_MODE_TEXT );
   	 GF_BGL_ScrClear( ini, GF_BGL_FRAME3_M );
 	}

	  //サブ
	{	/* SUB DISP BG0 */							//テキスト
 	   GF_BGL_BGCNT_HEADER SBg0_Data = {
    	  	0, 0, 0x800, 0,
   	  		GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
			GX_BG_SCRBASE_0xf800, GX_BG_CHARBASE_0x0c000,
    		GX_BG_EXTPLTT_01, 0, 0, 0, FALSE
  	  };
 	  GF_BGL_BGControlSet( ini, GF_BGL_FRAME0_S, &SBg0_Data, GF_BGL_MODE_TEXT );
  	  GF_BGL_ScrClear( ini, GF_BGL_FRAME0_S );
 	}

 	{	/* SUB DISP BG1 */							//点数表示
	    GF_BGL_BGCNT_HEADER SBg1_Data = {
    	  	0, 0, 0x800, 0,
 	  		GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
 	   		GX_BG_SCRBASE_0xf000, GX_BG_CHARBASE_0x04000,
  	   		GX_BG_EXTPLTT_01, 1, 0, 0, FALSE
		};
    	GF_BGL_BGControlSet( ini, GF_BGL_FRAME1_S, &SBg1_Data, GF_BGL_MODE_TEXT );
    	GF_BGL_ScrClear( ini, GF_BGL_FRAME1_S );
	}

	{	/* SUB DISP BG2 */							//ボード
		GF_BGL_BGCNT_HEADER SBg2_Data = {
			0, 0, 0x800, 0,
		    GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
      		GX_BG_SCRBASE_0xe800, GX_BG_CHARBASE_0x04000,
      		GX_BG_EXTPLTT_01, 2, 0, 0, FALSE
    	};
	    GF_BGL_BGControlSet( ini, GF_BGL_FRAME2_S, &SBg2_Data, GF_BGL_MODE_TEXT );
  	  	GF_BGL_ScrClear( ini, GF_BGL_FRAME2_S );
 	}

	{	/* SUB DISP BG3 */							//背景面
		GF_BGL_BGCNT_HEADER SBg3_Data = {
			0, 0, 0x800, 0,
		    GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
      		GX_BG_SCRBASE_0xe000, GX_BG_CHARBASE_0x00000,
      		GX_BG_EXTPLTT_01, 3, 0, 0, FALSE
    	};
	    GF_BGL_BGControlSet( ini, GF_BGL_FRAME3_S, &SBg3_Data, GF_BGL_MODE_TEXT );
  	  	GF_BGL_ScrClear( ini, GF_BGL_FRAME3_S );
 	 }

	//レコードＢＧ非表示
	GF_Disp_GX_VisibleControl( GX_PLANEMASK_BG3, VISIBLE_OFF );
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	グラフィックセット
 * @param	ptr			アプリポインタ
 * @param	inNetID		ネットID
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void SetGraphic(PKTHLN_THROW_PTR ptr, const u8 inNetID)
{
	//メインキャラ
	ArcUtil_BgCharSet(ARC_PKTHEV_THROW, NARC_pkthev_throw_throw_bg_main_ncgr,
						ptr->bgl, GF_BGL_FRAME1_M, 0, 0x4000, FALSE, ptr->HeapID);

	ArcUtil_ScrnSet(ARC_PKTHEV_THROW, NARC_pkthev_throw_throw_bg_main_nscr,
						ptr->bgl, GF_BGL_FRAME1_M, 0, 0, FALSE, ptr->HeapID);
	//メインパレット
	ArcUtil_PalSet( ARC_PKTHEV_THROW, NARC_pkthev_throw_throw_bg_main_nclr,
						PALTYPE_MAIN_BG, 0, 32, ptr->HeapID );
	//サブBG
	ThrowSub_SetBG(ptr->SubDispCntPtr, inNetID);

}

//----------------------------------------------------------------------------
/**
 *	@brief		ＯＢＪセット
 *
 *	@param	pActCntPtr		アクターコントローラポインタ
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void SetObj(PKTHLN_CLACT_CNT_PTR pActCntPtr)
{
	//上下共通
	PkthlnClAct_SetChar( pActCntPtr,
					ARC_PKTHEV_THROW, NARC_pkthev_throw_throw_obj_cmn_NCGR,
					RES_CODE_THROW_CMN, NNS_G2D_VRAM_TYPE_MAX);
	PkthlnClAct_SetPaltt( pActCntPtr,
					ARC_PKTHEV_THROW, NARC_pkthev_throw_throw_obj_cmn_NCLR,
					RES_CODE_THROW_CMN, NNS_G2D_VRAM_TYPE_MAX, THROW_OBJ_CMN_PAL_NUM	);
	PkthlnClAct_SetCell( pActCntPtr,
					ARC_PKTHEV_THROW, NARC_pkthev_throw_throw_obj_cmn_NCER, RES_CODE_THROW_CMN	);
	PkthlnClAct_SetAnm(	pActCntPtr,
					ARC_PKTHEV_THROW, NARC_pkthev_throw_throw_obj_cmn_NANR, RES_CODE_THROW_CMN	);

	//メイン
	PkthlnClAct_SetChar( pActCntPtr,
					ARC_PKTHEV_THROW, NARC_pkthev_throw_throw_obj_main_NCGR,
					RES_CODE_THROW_MAIN, NNS_G2D_VRAM_TYPE_2DMAIN);
	PkthlnClAct_SetPaltt( pActCntPtr,
					ARC_PKTHEV_THROW, NARC_pkthev_throw_throw_obj_main_NCLR,
					RES_CODE_THROW_MAIN, NNS_G2D_VRAM_TYPE_2DMAIN, THROW_OBJ_MAIN_PAL_NUM	);
	PkthlnClAct_SetCell( pActCntPtr,
					ARC_PKTHEV_THROW, NARC_pkthev_throw_throw_obj_main_NCER, RES_CODE_THROW_MAIN	);
	PkthlnClAct_SetAnm(	pActCntPtr,
					ARC_PKTHEV_THROW, NARC_pkthev_throw_throw_obj_main_NANR, RES_CODE_THROW_MAIN	);
}

//----------------------------------------------------------------------------
/**
 *	@brief	アクターセットアップ
 *
 *  @param	ptr				コントローラ
 *	@param	pActCntPtr		アクターコントローラポインタ
 *	@param	inNetID			ネットID
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void SetAct( PKTHLN_THROW_PTR ptr, PKTHLN_CLACT_CNT_PTR pActCntPtr, const u8 inNetID)
{
	int i;

	//共通リソース
	for(i=0;i<TIME_DIGI_MAX;i++){
		VecFx32 vec;
		ptr->TimeActPtr[i] = CmnRes_CreateF2X2Act( ptr->CmnResCntPtr,
												   PkthlnClAct_GetClActSetAdr(pActCntPtr),
												   OBJ_BG_PRI,
												   ptr->HeapID );
		CLACT_SetDrawFlag(ptr->TimeActPtr[i], 1);	//表示
		//座標セット
		vec.x = TIMER_ACT_POS_X + (TIMER_ACT_W*i*FX32_ONE);
		vec.y = TIMER_ACT_POS_Y;
		vec.z = 0;
		CLACT_SetMatrix(ptr->TimeActPtr[i], &vec);
		CLACT_DrawPriorityChg(ptr->TimeActPtr[i], PRI_TIME);
	}
	DispTime(ptr, GAME_TIME/30);

	//↓上下共通

	//玉、玉影、粉砕
	for (i=0;i<BALL_NUM_MAX;i++){
		ptr->Ball[i].OrgIdx = i;
		ptr->Ball[i].BallActPtr =
			PkthlnClAct_SetGetActor(pActCntPtr, OBJ_BG_PRI, NNS_G2D_VRAM_TYPE_MAX,
										RES_CODE_THROW_CMN, ACT_CODE_THROW_BALL);
		ptr->Ball[i].ShdwActPtr =
			PkthlnClAct_SetGetActor(pActCntPtr, OBJ_BG_PRI, NNS_G2D_VRAM_TYPE_MAX,
										RES_CODE_THROW_CMN, ACT_CODE_THROW_BSHDW);
		ptr->Ball[i].BreakActPtr =
			PkthlnClAct_SetGetActor(pActCntPtr, OBJ_BG_PRI, NNS_G2D_VRAM_TYPE_MAX,
										RES_CODE_THROW_CMN, ACT_CODE_THROW_BREAK);
		PkthlnClAct_ChgAnm(ptr->Ball[i].ShdwActPtr, 1);

		//プライオリティ
		PkthlnClAct_SetPriority(ptr->Ball[i].BallActPtr, PRI_BALL);
		PkthlnClAct_SetPriority(ptr->Ball[i].ShdwActPtr, PRI_BALL_SHDW);
		PkthlnClAct_SetPriority(ptr->Ball[i].BreakActPtr, PRI_BREAK);
	}

	//気絶
	for (i=0;i<THROW_EVENT_POKE_NUM_ALL;i++){
		ptr->Poke[i].PanicActPtr =
			PkthlnClAct_SetGetActor(pActCntPtr, OBJ_BG_PRI, NNS_G2D_VRAM_TYPE_MAX,
										RES_CODE_THROW_CMN, ACT_CODE_THROW_PANIC);
		PkthlnClAct_ChgAnm(ptr->Poke[i].PanicActPtr, 2);
		//座標セット
		{
			VecFx32 vec;
			vec.x = FX32_ONE;
			vec.y = FX32_ONE;
			vec.z = 0;
			PkthlnClAct_SetPos(ptr->Poke[i].PanicActPtr, &vec);
		}
		PkthlnClAct_SetPriority(ptr->Poke[i].PanicActPtr, PRI_PANIC);
	}

	//↓ここから上画面

	//ポイント取得
	for (i=0;i<ENTRY_MAX;i++){
		ptr->PointActPtr[i] =
			PkthlnClAct_SetGetActor(pActCntPtr, OBJ_BG_PRI-1, NNS_G2D_VRAM_TYPE_2DMAIN,
										RES_CODE_THROW_MAIN, ACT_CODE_THROW_POINT);
		PkthlnClAct_ChgAnm(ptr->PointActPtr[i], POINT_ANM_OFS);
		PkthlnClAct_SetPriority(ptr->PointActPtr[i], PRI_POINT);
	}

	//時計
	ptr->WatchActPtr = PkthlnClAct_SetGetActor(pActCntPtr, OBJ_BG_PRI, NNS_G2D_VRAM_TYPE_2DMAIN,
				RES_CODE_THROW_MAIN, ACT_CODE_THROW_WATCH);
	//座標セット
	{
		VecFx32 vec;
		vec.x = WATCH_X;
		vec.y = WATCH_Y;
		vec.z = 0;
		PkthlnClAct_SetPos(ptr->WatchActPtr, &vec);
	}
	//可視
	PkthlnClAct_ChgAnm(ptr->WatchActPtr, 5);
	PkthlnClAct_SetActive(ptr->WatchActPtr, 1, 1);
	PkthlnClAct_SetPriority(ptr->WatchActPtr, PRI_WATCH);
	//旗
	{
		u8 base;
		VecFx32 vec[ENTRY_MEMBER_NUM_MAX-1] = {
			{FLAG1_X,FLAG1_Y,0},
			{FLAG2_X,FLAG2_Y,0},
			{FLAG3_X,FLAG3_Y,0},
		};

		base = (inNetID+1)%ENTRY_MEMBER_NUM_MAX;
		for(i=0;i<ENTRY_MEMBER_NUM_MAX-1;i++){
			ptr->FlagActPtr[i] = PkthlnClAct_SetGetActor(pActCntPtr, OBJ_BG_PRI,
					NNS_G2D_VRAM_TYPE_2DMAIN, RES_CODE_THROW_MAIN, ACT_CODE_THROW_FLAG);
			//座標セット
			PkthlnClAct_SetPos(ptr->FlagActPtr[i], &vec[i]);
			//可視
			PkthlnClAct_ChgAnm(ptr->FlagActPtr[i], 1+base);
			PkthlnClAct_SetActive(ptr->FlagActPtr[i], 1, 1);
			base = (base+1)%ENTRY_MEMBER_NUM_MAX;
			PkthlnClAct_SetPriority(ptr->FlagActPtr[i], PRI_FLAG);
		}
	}

	//汗
	for (i=0;i<THROW_EVENT_POKE_NUM;i++){
		ptr->SweatActPtr[i] = PkthlnClAct_SetGetActor(pActCntPtr, OBJ_BG_PRI,
					NNS_G2D_VRAM_TYPE_2DMAIN, RES_CODE_THROW_MAIN, ACT_CODE_THROW_MAIN_SWEAT);
		PkthlnClAct_ChgAnm(ptr->SweatActPtr[i], 0);
		PkthlnClAct_SetPriority(ptr->SweatActPtr[i], PRI_SWEAT);
	}

}

//----------------------------------------------------------------------------
/**
 *	@brief	シーケンス関数
 *
 *	@param	work		ポケスロンポインタ
 *	@param	*seq		シーケンサ
 *
 *	@return	FALSE
 */
//-----------------------------------------------------------------------------
static BOOL THROW_Func_Phase0(PKTHLN_PTR work, u8 *seq)
{
	BOOL rc;
	PKTHLN_THROW_PTR ptr = PTFrame_GetEventWorkPtr(work);

	switch(*seq){
	case 0:	//カウント
		if ( PTFrame_CountDown(work) ){
			(*seq)++;
		}
		break;
	case 1:
		CommMain(work);
		if ( ControlMain(work) ){
			(*seq)++;
		}
		break;
	case 2:
		CommMain(work);
		if ( PTFrame_DispEnd(work) ){
			//フェードアウトリクエスト
			WIPE_SYS_Start(	WIPE_PATTERN_WMS, WIPE_TYPE_FADEOUT,
							WIPE_TYPE_FADEOUT, WIPE_FADE_BLACK,
							WIPE_DEF_DIV, WIPE_DEF_SYNC, ptr->HeapID );
			//シーケンスシフト
			PTFrame_SetNextFuncTblIdx(work, THROW_SEQ_PHASE1);
		}
		break;
	}


	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	シーケンス関数
 *
 *	@param	work		ポケスロンポインタ
 *	@param	*seq		シーケンサ
 *
 *	@return	TRUE
 */
//-----------------------------------------------------------------------------
static BOOL THROW_Func_Phase1(PKTHLN_PTR work, u8 *seq)
{
	int i,j;
	PKTHLN_THROW_PTR ptr;
	THROW_PARENT_DATA *parent;
	COMM_EVENT_COMMON_DATA *data;
	data = PTFrame_GetEvtComCmnData(work);
	ptr = PTFrame_GetEventWorkPtr(work);

	if (*seq == 0){
		//フェードアウト待ち
		if ( WIPE_SYS_EndCheck() ){
			*seq = 1;
		}
		return FALSE;
	}

	//結果はすべて親が管理しているので、子は処理をスルー
	if (PTFrameGetCurrentID(work) != COMM_PARENT_ID){
		return TRUE;
	}

	parent = PKTHLN_CommPack_GetData(&data->SendShareData);
	//結果セット
	for (i=0;i<ENTRY_MEMBER_NUM_MAX;i++){
		int point;
		point = parent->Prm[i] & 0x3ff;	//10ビットマスク
		PTFrame_SetEvtResultOrg(work, i, point);
	}
	return TRUE;
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	通信データ関連メイン処理
 * @param	work		ポケスロンポインタ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void CommMain(PKTHLN_PTR work)
{
	int i,j;
	PKTHLN_THROW_PTR ptr;
	THROW_CHILD_DATA *child_data;
	THROW_PARENT_DATA *parent;
	COMM_EVENT_COMMON_DATA *data;
	data = PTFrame_GetEvtComCmnData(work);
	ptr = PTFrame_GetEventWorkPtr(work);

#ifdef PM_DEBUG
	PokeGraDebugMain(ptr->SubDispCntPtr);
#endif

	//親動作
	if (PTFrameGetCurrentID(work) == COMM_PARENT_ID){
		//終了フラグが立っているならば、通信データのセットのみを行い処理を打ち切る
		if (ptr->EndFlg){
			//情報セット
			SetCommInfo(ptr,  PKTHLN_CommPack_GetData(&data->SendShareData));
			return;
		}

		//親データは直接レシーバにセット
		{
			THROW_CHILD_DATA *child;
			THROW_CHILD_DATA *child_rec;

			child_rec = PKTHLN_CommPack_GetData(&data->ReciveData[0]);
			child = PKTHLN_CommPack_GetData(&data->SendData);
			(*child_rec) = (*child);
		}

		//時間経過
#ifdef PM_DEBUG					//こっちデバッグ用
		if (!DebugPkthlnWk.TimeInfinity){
			if (ptr->CommTime > 0){
				ptr->CommTime--;
			}
		}
#else							//こっち製品用
		if (ptr->CommTime > 0){
			ptr->CommTime--;
		}
#endif
		parent = PKTHLN_CommPack_GetData(&data->SendShareData);

		//プレーヤー数ループ
		for(i=0;i<ENTRY_MEMBER_NUM_MAX;i++){
			THROW_CHILD_DATA *child_data;
			child_data = PKTHLN_CommPack_GetData(&data->ReciveData[i]);
			//タッチ状況を整理
			if (child_data->TouchValid){
				if ( (ptr->TpState[i].Trg)&&(ptr->TpState[i].Cont) ){
					ptr->TpState[i].Trg = FALSE;
				}else if((!ptr->TpState[i].Trg)&&(!ptr->TpState[i].Cont)){
					ptr->TpState[i].Trg = TRUE;
					ptr->TpState[i].Cont = TRUE;
				}
			}else{
				ptr->TpState[i].Trg = FALSE;
				ptr->TpState[i].Cont = FALSE;
			}

			if (1){
				u8 poke_idx;
				if (ptr->TpState[i].Trg){
					VecFx32 vec;
					//ポケモンをタッチしたかを検出
					poke_idx = CheckPokeTouch(ptr, i, child_data->TpX, child_data->TpY, &vec);
					//自分のポケか？
					if ( poke_idx != THROW_EVENT_POKE_NUM_ALL ){

						//行動不能ならば、処理をスルー
						if (ptr->Poke[poke_idx].StopTime > 0){
							continue;
						}

						if ((ptr->Ball[poke_idx].State == BALL_ST_NONE)||
							(ptr->Ball[poke_idx].State == BALL_ST_SET)){
							//ホールド登録
							ptr->HoldPoke[i] = poke_idx;
							//ボールの発射位置記憶
							ptr->Ball[poke_idx].ShotPos = vec;
							//自分の画面のタッチ座標を記憶
							{
								VecFx32 touch_vec;
								touch_vec.x = child_data->TpX * FX32_ONE;
								touch_vec.z = child_data->TpY * FX32_ONE;
								touch_vec.y = 0;
								ptr->Ball[poke_idx].TouchPos = touch_vec;
							}
							if (ptr->Ball[poke_idx].State == BALL_ST_NONE){
								//ボールセット
								ptr->Ball[poke_idx].Pos = ChkPokePos[poke_idx];
								ptr->Ball[poke_idx].State = BALL_ST_SET;
								ptr->Ball[poke_idx].Level = 0;
								ptr->Ball[poke_idx].Size = 0;
								OS_Printf("ボールセット\n");
							}
						}
					}
					//タッチ時間カウントスタート
					ptr->TouchTime = 0;
				}else if (ptr->TpState[i].Cont){	//ベタ押し
					//ホールドポケいなければ、処理しない
					if (ptr->HoldPoke[i] == THROW_EVENT_POKE_NUM_ALL){
						continue;
					}
					//タッチ時間カウント
					if (ptr->TouchTime < TOUCH_TIME_MAX){
						ptr->TouchTime++;
					}
					//ベタタッチ座標更新
///					ptr->Poke[i].LastTPos.x = child_data->TpX * FX32_ONE;
///					ptr->Poke[i].LastTPos.y = child_data->TpY * FX32_ONE;
				}else{	//タッチしていない
					if ( ptr->HoldPoke[i] != THROW_EVENT_POKE_NUM_ALL ){
						VecFx32 vec;
						//ポケモンをタッチしたかを検出
						poke_idx = CheckPokeTouch(ptr, i, child_data->TpX, child_data->TpY, &vec);
						if ( (poke_idx != THROW_EVENT_POKE_NUM_ALL)&&(poke_idx == ptr->HoldPoke[i])  ){
							//玉を大きくする
							OS_Printf("玉を大きくする\n");
							if (ptr->Ball[poke_idx].Level < LEVEL_MAX){
								ptr->Ball[poke_idx].Level++;
								if (ptr->Ball[poke_idx].Level <= LV_FST){
									ptr->Ball[poke_idx].Size = 0;
								}else if(ptr->Ball[poke_idx].Level <= LV_2ND){
									ptr->Ball[poke_idx].Size = 1;
								}else if(ptr->Ball[poke_idx].Level <= LV_3RD){
									ptr->Ball[poke_idx].Size = 2;
								}else{
									ptr->Ball[poke_idx].Size = 3;
								}
							}
						}else{
							float cof,time_cof;
							float flt_len;
							VecFx32 add = {0,0,0};
							VecFx32 dir;
							VecFx32 strk_dir;

							u8 poke_idx;
							poke_idx = ptr->HoldPoke[i];

							//ストローク方向を算出
							OS_Printf("ストローク算出 ホールドポケ＝%d\n",poke_idx);
							VEC_Subtract(&vec, &ptr->Ball[poke_idx].ShotPos, &dir);
							{
								VecFx32 touch_vec;
								touch_vec.x = child_data->TpX * FX32_ONE;
								touch_vec.z = child_data->TpY * FX32_ONE;
								touch_vec.y = 0;
								VEC_Subtract(&touch_vec, &ptr->Ball[poke_idx].TouchPos, &strk_dir);
							}

							if (strk_dir.z <= 0){
								ptr->Ball[poke_idx].Dir = dir;

								OS_Printf("長さ:%d\n",VEC_Mag(&ptr->Ball[poke_idx].Dir));
								//打ち出すときのHP残量別に係数を決定
								if (ptr->Poke[poke_idx].Hp <= 60 ){
									cof = 0.5;
								}else if(ptr->Poke[poke_idx].Hp <= 70){
									cof = 0.6;
								}else if(ptr->Poke[poke_idx].Hp <= 80){
									cof = 0.7;
								}else if(ptr->Poke[poke_idx].Hp <= 90){
									cof = 0.8;
								}else{
									cof = 1.0;
								}

								flt_len = (float)(VEC_Mag(&ptr->Ball[poke_idx].Dir)/FX32_ONE);
								OS_Printf("float_len = %f\n",flt_len);
								//長さに制限をつける
								if (flt_len > BALL_SPD_MAX){
									flt_len = BALL_SPD_MAX;
								}else if(flt_len < BALL_SPD_MIN){
									flt_len = BALL_SPD_MIN;
								}
								//タッチ時間補正値
								time_cof = ((float)ptr->TouchTime/TOUCH_TIME_MAX)+1.0;
								flt_len = flt_len * (2.0-ptr->Poke[poke_idx].Technique2) * cof / time_cof;
///								OS_Printf("係数%f\n",flt_len);
								//補正
								if (flt_len > BALL_SPD_MAX2){
									flt_len = BALL_SPD_MAX2;
								}else if(flt_len < BALL_SPD_MIN){
									flt_len = BALL_SPD_MIN;
								}
///								OS_Printf("補正後係数%f\n",flt_len);
								VEC_Normalize(&ptr->Ball[poke_idx].Dir, &ptr->Ball[poke_idx].Dir);
								VEC_MultAdd(flt_len*FX32_ONE, &ptr->Ball[poke_idx].Dir, &add, &ptr->Ball[poke_idx].Dir);
///								OS_Printf("FIX長さ:%d\n",VEC_Mag(&ptr->Ball[poke_idx].Dir));
								//テクニックによる方向変更
								ThClc_FixDir(ptr->Poke[poke_idx].Technique, &ptr->Ball[poke_idx].Dir);
/**
								OS_Printf("org:%d,%d dst:%d,%d\n",
										ptr->Ball[poke_idx].ShotPos.x/FX32_ONE,ptr->Ball[poke_idx].ShotPos.z/FX32_ONE,
										vec.x/FX32_ONE, vec.z/FX32_ONE);
*/
								ptr->Ball[poke_idx].State = BALL_ST_MOVE;
							}else{
								OS_Printf("下方向\n");
							}
						}
						//ホールド解除
						ptr->HoldPoke[i] = THROW_EVENT_POKE_NUM_ALL;
					}
					//タッチタイムクリア
					ptr->TouchTime = 0;
				}
			}//end if (ptr->Poke[i].ChgFlg)
		}	//end for(i=0;i<ENTRY_MEMBER_NUM_MAX;i++)

		//AI実行
#ifdef PM_DEBUG										//こっちデバッグ用
		if ( !DebugPkthlnWk.AI_Stop ){
			ThrowAI_Execute(ptr->AICntPtr, GAME_TIME - ptr->CommTime);
		}
#else												//こっち製品用
		ThrowAI_Execute(ptr->AICntPtr, GAME_TIME - ptr->CommTime);
#endif

		//ポケの処理
		MovePoke(work);
		//玉の制御
		MoveBall(work);
		//玉同士のあたり判定
		HitCheckBall(ptr);
		//当たり判定
		HitCheckPoke(work, ptr);

		//終了判定
		if (ptr->CommTime <= 0){
			ptr->EndFlg = 1;		//終了フラグ
		}else{
			ptr->EndFlg = 0;
		}

		//情報セット
		SetCommInfo(ptr,  PKTHLN_CommPack_GetData(&data->SendShareData));
	}
}

//--------------------------------------------------------------------------------------------
/**
 * @brief	通信データセット
 * @param	ptr		ポケスロンアプリポインタ
 * @param	parent	親データ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void SetCommInfo(PKTHLN_THROW_PTR ptr, THROW_PARENT_DATA *parent)
{
	int i;
	int b_st;
	u8 ball_size_set[ENTRY_MEMBER_NUM_MAX] = {0,0,0,0};
	u16 point[ENTRY_MEMBER_NUM_MAX] = {0,0,0,0};
	b_st = 0;
#if 0
#ifdef PM_DEBUG
	//デバッグ処理
	if (sys.trg & PAD_BUTTON_A){
		//デバッグ処理開始
		dbg_w.main_start = 1;
		dbg_w.test_sync = 0;
	}
	if (dbg_w.main_start){
		//対象のポケにダメージを与える
		ptr->Poke[8].Hit = 1;
		ptr->Poke[8].StopTime = 320;
		dbg_w.test_sync++;
		//２シンク行う
		if (dbg_w.test_sync>=2){
			dbg_w.main_start = 0;
			dbg_w.test_sync = 0;
		}
	}
#endif
#endif

	for(i=0;i<THROW_EVENT_POKE_NUM_ALL;i++){
		int x,z;
		u8 p_get;
		u8 hit;
		b_st |= ptr->Ball[i].State << (2*i);
		hit = ptr->Poke[i].Hit;
		if (ptr->Ball[i].PointGet){
			p_get = 1;
		}else{
			p_get = 0;
		}
		//セットしたら得点取得フラグおとす
		ptr->Ball[i].PointGet = 0;

		x = ptr->Ball[i].Pos.x/FX32_ONE;
		z = ptr->Ball[i].Pos.z/FX32_ONE;
		//範囲修正
		if (x<1){
			x = 1;
		}else if(x>64){
			x = 64;
		}
		if (z<1){
			z = 1;
		}else if(z>64){
			z = 64;
		}

		//通信で送るために丸め込みのためマイナス1する(0〜63)
		x-=1;
		z-=1;
		ball_size_set[i/ENTRY_MAX] += ( ptr->Ball[i].Size << ((i%ENTRY_MAX)*2) );
		parent->Prm2[i] = x+(z<<6)+(hit<<12)+(p_get<<13)+(ptr->Poke[i].State<<14);
		point[i/ENTRY_MAX] += ptr->Poke[i].Point;
		if (point[i/ENTRY_MAX] > POINT_MAX){
			point[i/ENTRY_MAX] = POINT_MAX;
		}
	}

	for (i=0;i<ENTRY_MEMBER_NUM_MAX;i++){
		parent->Prm[i] = point[i] + (ball_size_set[i]<<10);
	}

	parent->Prm3 = b_st;
	parent->Prm3 += ( ptr->EndFlg <<24 );
	parent->Prm3 += ( ( (ptr->CommTime+30)/30 ) << 25 );
}

//----------------------------------------------------------------------------
/**
 *	@brief		メイン関数
 *
 *	@param	work	ポケスロンポインタ
 *
 *	@return	終了でTRUE
 */
//-----------------------------------------------------------------------------
static BOOL ControlMain(PKTHLN_PTR work)
{
	PKTHLN_THROW_PTR ptr = PTFrame_GetEventWorkPtr(work);

	THROW_CHILD_DATA *child_data;
	COMM_EVENT_COMMON_DATA *data;
	data = PTFrame_GetEvtComCmnData(work);
	child_data = PKTHLN_CommPack_GetData(&data->SendData);
	child_data->TouchValid = FALSE;

	//終了検出
	{
		u8 end;
		THROW_PARENT_DATA *parent;
		parent = PKTHLN_CommPack_GetData(&data->ReciveShareData);
		end = (parent->Prm3 >> 24) & 0x1;	//1ビットマスク
#ifdef PM_DEBUG
		if (sys.trg & PAD_BUTTON_X){
			end = 1;
		}
#endif
		if (end){
			//アクター停止
			PkthlnClAct_AllAnmStop(ptr->ActCntPtr, 1);
			PokeAct_AllAnmStop(ptr->PokeActCntPtr, 1);
/**
			//フレームワークにニューレコードチェック用のレコード値をセット
			PTFrame_SetCheckRecord(work, point);
			SetRecordStr(ptr, point);
*/
			//レコードコールバック関数をセット
			PTFrame_SetRecordCallBack(work, RecCallBack);
			return TRUE;
		}
	}

	//タッチ座標検出
	if (GF_TP_GetTrg()){
		//アクションポイント加算「タッチ回数」
		PTFrame_AddActionPoint(	work, PTFrameGetCurrentID(work), ENTRY_MAX, ADD_TYPE_TOUCH, 1 );
	}
	if (GF_TP_GetCont()){
		//通信データに座標をセット
		child_data->TpX = sys.tp_x;
		child_data->TpY = sys.tp_y;
		child_data->TouchValid = TRUE;
	}

	SetDraw(work);

	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief		描画座標関連セット関数
 *
 *	@param	work	ポケスロンポインタ
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void SetDraw(PKTHLN_PTR work)
{
	int i;
	u8 my_net_id;
	COMM_EVENT_COMMON_DATA * data;
	THROW_PARENT_DATA *parent;
	u8 time;

	PKTHLN_THROW_PTR ptr = PTFrame_GetEventWorkPtr(work);

	data = PTFrame_GetEvtComCmnData(work);
	parent = PKTHLN_CommPack_GetData(&data->ReciveShareData);
	my_net_id = PTFrameGetCurrentID(work);

	//時間表示
	{
		u8 disp_time;
		time = (parent->Prm3 >> 25 ) & 0x7f;	//7ビットマスク
		if(time==0){
			disp_time = 0;
		}else{
			disp_time = time-1;
		}
		DispTime(ptr, disp_time);
	}
	//得点表示
	{
		u16 point;
		point = parent->Prm[my_net_id] & 0x3ff;	//10ビットマスク
		ThrowSub_FillPoint(ptr->SubDispCntPtr, point);

		//得点取得
		for(i=0;i<THROW_EVENT_POKE_NUM_ALL;i++){
			u8 get;
			get = (parent->Prm2[i] >> 13) & 0x1;	//1ビットマスク
			if (get && (my_net_id == i/ENTRY_MAX)){
				int ball_x, ball_z, dx, dy;
				VecFx32 vec;
				u8 point_idx = i%ENTRY_MAX;
				//ポイント取得表示
				PkthlnClAct_SetActive(ptr->PointActPtr[point_idx], 1, 1);
				PkthlnClAct_ChgAnm(ptr->PointActPtr[point_idx], POINT_ANM_OFS);
				//座標セット
				ball_x = parent->Prm2[i] & 0x3f;	//6ビットマスク
				ball_z = (parent->Prm2[i]>>6) & 0x3f;	//6ビットマスク
				//元に戻す
				ball_x+=1;
				ball_z+=1;
				//取得座標を回転
				if (my_net_id != COMM_PARENT_ID){
					u8 mul;
					MtxFx43 mtx;
					VecFx32 base, fix;
					base.x = ball_x * FX32_ONE;
					base.z = ball_z * FX32_ONE;
					base.y = 0;
					//原点回転になるように、点を平行移動
					base.x -= (33*FX32_ONE);
					base.z -= (33*FX32_ONE);
					//回転行列作成
					mul = (ENTRY_MEMBER_NUM_MAX-my_net_id);
					MTX_RotY43(&mtx, FX_SinIdx(0x4000*mul), FX_CosIdx(0x4000*mul));
					//ベクトルと行列を掛け合わせる
					MTX_MultVec43(&base, &mtx, &fix);
					//もとの位置に平行移動
					fix.x += (33*FX32_ONE);
					fix.z += (33*FX32_ONE);
					ball_x = fix.x / FX32_ONE;
					ball_z = fix.z / FX32_ONE;
				}
				ThClc_GetDspPosFromChkPos(ball_x, ball_z, &dx, &dy);
				vec.x = dx * FX32_ONE;
				vec.y = dy * FX32_ONE;
				vec.z = 0;
				//ボールの位置に
				vec.y = (dy-8-(dy/20)) * FX32_ONE;
				PkthlnClAct_SetPos(ptr->PointActPtr[point_idx], &vec);

				Snd_SePlay( SE_THROW_ENEMY_HIT );		//得点取得ＳＥ
			}
		}
	}

	//ポケモン関連
	{
		u8 state;
		u8 idx;
		u8 base_idx;
		//自ポケ
		for(i=0;i<ENTRY_MAX;i++){
			idx = my_net_id*ENTRY_MAX+i;
			state = (parent->Prm2[idx] >> 14) & 0x3;		//2ビットマスク
			if (state == POKE_ST_PANIC){
				PkthlnClAct_SetActive(ptr->Poke[idx].PanicActPtr, 1, 1);
				ThrowSub_SetDrawSweat(ptr->SubDispCntPtr, i, 0);
			}else if(state == POKE_ST_FATIGUE){
				PkthlnClAct_SetActive(ptr->Poke[idx].PanicActPtr, 1, 0);
				ThrowSub_SetDrawSweat(ptr->SubDispCntPtr, i, 1);
			}else{
				PkthlnClAct_SetActive(ptr->Poke[idx].PanicActPtr, 1, 0);
				ThrowSub_SetDrawSweat(ptr->SubDispCntPtr, i, 0);
			}
			//モーション
			{
				u8 hit;
				u8 b_st;
				int ball_x,ball_z;
				hit = (parent->Prm2[idx] >> 12) & 0x1;	//1ビットマスク
				//ボール座標取得
				b_st = (parent->Prm3 >> (2*idx)) & 0x3;		//2ビットマスク
				ball_x = parent->Prm2[idx] & 0x3f;	//6ビットマスク
				ball_z = (parent->Prm2[idx]>>6) & 0x3f;	//6ビットマスク
				//元に戻す
				ball_x+=1;
				ball_z+=1;
				if(state == POKE_ST_PANIC){	//気絶
					ThrowSub_ChgPokeAnm(ptr->SubDispCntPtr, i, MY_POKE_ANM_PANIC);
					ptr->Poke[idx].PokeAnm = MY_POKE_ANM_PANIC;
					//再生終了していたら
					if( Snd_SePlayCheck(SE_THLON_RUNNING_OUT) == FALSE ){
						Snd_SePlay( SE_THLON_RUNNING_OUT );	//自分気絶SE。ここにおくと気絶中はずっとコールされます
					}
					if (hit){		//ダメージ受けていたら、SEは鳴らす（モーションは気絶優先）
						Snd_SePlay( SE_THROW_MINE_HIT );		//ダメージＳＥ
					}
				}else if (hit){		//ダメージ
					ThrowSub_ChgPokeAnm(ptr->SubDispCntPtr, i, MY_POKE_ANM_HIT);
					ptr->Poke[idx].PokeAnm = MY_POKE_ANM_HIT;
					Snd_SePlay( SE_THROW_MINE_HIT );		//ダメージＳＥ
					//画面揺らしリクエスト
					ThrowSub_DispShakeRequest(ptr->SubDispCntPtr);
				}else if( (b_st == BALL_ST_MOVE)&&(!ptr->Poke[idx].ThrowAnmFlg) ){	//投げる
					//気絶中は投げられない
					GF_ASSERT_MSG((state != POKE_ST_PANIC),"MY_PANIC_STATE\n");
					ThrowSub_ChgPokeAnm(ptr->SubDispCntPtr, i, MY_POKE_ANM_THROW);
					ptr->Poke[idx].PokeAnm = MY_POKE_ANM_THROW;
					ptr->Poke[idx].ThrowAnmFlg = 1;		//投げた
					if (!ptr->ThrowSeFlg[i]){
						Snd_SePlay( SE_THROW_BALL );		//投げるＳＥ
					}
				}else {			//通常
					u8 anm = 0;
					if (ptr->Poke[idx].PokeAnm == MY_POKE_ANM_PANIC){
						anm = 1;
					}else if( !ThrowSub_PokeAnmCheck(ptr->SubDispCntPtr, i) ){
						anm = 1;
					}
					if (anm){
						ThrowSub_ChgPokeAnm(ptr->SubDispCntPtr, i, MY_POKE_ANM_NORMAL);
						ptr->Poke[idx].PokeAnm = MY_POKE_ANM_NORMAL;
					}
				}

				//ボールステートがBALL_ST_MOVE以外ならば、投げるアニメフラグを落とす
				if (b_st != BALL_ST_MOVE){
					ptr->Poke[idx].ThrowAnmFlg = 0;
				}
			}
		}
		//他ポケ
		base_idx = (my_net_id*ENTRY_MAX+ENTRY_MAX)%THROW_EVENT_POKE_NUM_ALL;
		for(i=0;i<THROW_EVENT_POKE_NUM;i++){
			idx = (base_idx+i)%THROW_EVENT_POKE_NUM_ALL;
			state = (parent->Prm2[idx] >> 14) & 0x3;		//2ビットマスク
			if (state == POKE_ST_PANIC){
				PkthlnClAct_SetActive(ptr->Poke[idx].PanicActPtr, 1, 1);
				PkthlnClAct_SetActive(ptr->SweatActPtr[i], 1, 0);	//不可視
			}else if(state == POKE_ST_FATIGUE){
				PkthlnClAct_SetActive(ptr->Poke[idx].PanicActPtr, 1, 0);
				PkthlnClAct_SetActive(ptr->SweatActPtr[i], 1, 1);	//可視
			}else{
				PkthlnClAct_SetActive(ptr->Poke[idx].PanicActPtr, 1, 0);
				PkthlnClAct_SetActive(ptr->SweatActPtr[i], 1, 0);
			}

			//モーション
			{
				u8 hit;
				u8 b_st;
				int ball_x,ball_z;
				hit = (parent->Prm2[idx] >> 12) & 0x1;	//1ビットマスク
				//ボール座標取得
				b_st = (parent->Prm3 >> (2*idx)) & 0x3;		//2ビットマスク
				ball_x = parent->Prm2[idx] & 0x3f;	//6ビットマスク
				ball_z = (parent->Prm2[idx]>>6) & 0x3f;	//6ビットマスク
				//元に戻す
				ball_x+=1;
				ball_z+=1;
				if(state == POKE_ST_PANIC){	//気絶
					PokeAct_SetAnm(ptr->PokeActPtr[i], ANM_TYPE_PANIC);
					ptr->Poke[idx].PokeAnm = ANM_TYPE_PANIC;

					//再生終了していたら
					if( Snd_SePlayCheck(SE_THLON_RUNNING_OUT) == FALSE ){
						Snd_SePlay( SE_THLON_RUNNING_OUT );	//敵気絶SE。ここにおくと気絶中はずっとコールされます
					}
				}else if (hit){		//ダメージ
					PokeAct_SetAnm(ptr->PokeActPtr[i], ANM_TYPE_DAMAGE);
					ptr->Poke[idx].PokeAnm = ANM_TYPE_DAMAGE;
				}else if( (b_st == BALL_ST_MOVE)&&
						(ball_x == ChkPokePos[idx].x/FX32_ONE) &&
						(ball_z == ChkPokePos[idx].z/FX32_ONE) ){	//投げる
					//気絶中は投げられない
					GF_ASSERT_MSG((state != POKE_ST_PANIC),"ENE_PANIC_STATE\n");

					PokeAct_SetAnm(ptr->PokeActPtr[i], ANM_TYPE_THROW);
					ptr->Poke[idx].PokeAnm = ANM_TYPE_THROW;
				}else{			//通常
					u8 anm = 0;
					if (ptr->Poke[idx].PokeAnm == ANM_TYPE_PANIC){
						anm = 1;
					}else if ( !PokeAct_AnmActiveCheck(ptr->PokeActPtr[i]) ){
						anm = 1;
					}
					if (anm){
						PokeAct_SetAnm(ptr->PokeActPtr[i], ANM_TYPE_WALK);
						ptr->Poke[idx].PokeAnm = ANM_TYPE_WALK;
					}
				}
			}
		}
	}

	//ボール動かしてみる
	for(i=0;i<THROW_EVENT_POKE_NUM_ALL;i++){
		VecFx32 vec;
		int ball_x,ball_z;
		int dx,dy;
		u8 b_st;
		u8 ball_size;

		b_st = (parent->Prm3 >> (2*i)) & 0x3;		//2ビットマスク
		if ( (b_st == BALL_ST_MOVE)||(b_st == BALL_ST_SET) ){
			//エフェクト検出フラグオフ
			ptr->Ball[i].BreakFlg = 0;
			//表示
			if (b_st != BALL_ST_SET){
				PkthlnClAct_SetActive(ptr->Ball[i].ShdwActPtr, 1, 1);	//可視でセット
			}else{
				PkthlnClAct_SetActive(ptr->Ball[i].ShdwActPtr, 1, 0);	//可視でセット
			}
			PkthlnClAct_SetActive(ptr->Ball[i].BallActPtr, 1, 1);	//可視でセット

			//ボールサイズ取得
			ball_size = (parent->Prm[i/ENTRY_MAX] >> 10) & 0x3F;	//6ビットマスク
			ball_size = (ball_size >> ((i%ENTRY_MAX)*2)) & 0x3;		//2ビットマスク

			ball_x = parent->Prm2[i] & 0x3f;	//6ビットマスク
			ball_z = (parent->Prm2[i]>>6) & 0x3f;	//6ビットマスク
			//元に戻す
			ball_x+=1;
			ball_z+=1;

			//取得座標を回転
			if (my_net_id != COMM_PARENT_ID){
				u8 mul;
				MtxFx43 mtx;
				VecFx32 base, fix;
				base.x = ball_x * FX32_ONE;
				base.z = ball_z * FX32_ONE;
				base.y = 0;
				//原点回転になるように、点を平行移動
				base.x -= (33*FX32_ONE);
				base.z -= (33*FX32_ONE);
				//回転行列作成
				mul = (ENTRY_MEMBER_NUM_MAX-my_net_id);
				MTX_RotY43(&mtx, FX_SinIdx(0x4000*mul), FX_CosIdx(0x4000*mul));
				//ベクトルと行列を掛け合わせる
				MTX_MultVec43(&base, &mtx, &fix);
				//もとの位置に平行移動
				fix.x += (33*FX32_ONE);
				fix.z += (33*FX32_ONE);
				ball_x = fix.x / FX32_ONE;
				ball_z = fix.z / FX32_ONE;
			}
			ThClc_GetDspPosFromChkPos(ball_x, ball_z, &dx, &dy);
///			OS_Printf("Ball:%d,%d\n",dx,dy);

			//影
			vec.x = dx * FX32_ONE;
			vec.y = dy * FX32_ONE;
			vec.z = 0;
			PkthlnClAct_SetPos(ptr->Ball[i].ShdwActPtr, &vec);

			//ボール
			vec.y = (dy-8-(dy/20)) * FX32_ONE;
			PkthlnClAct_SetPos(ptr->Ball[i].BallActPtr, &vec);

			//拡縮
			{
				float y, scl;
				VecFx32 scale = {FX32_ONE,FX32_ONE,FX32_ONE};
				y = dy;
				scl = (y+312.0)/752.0 * ( (float)(ball_size)/3.0+1.0 );
///				OS_Printf("scl = %f\n",scl);
				scale.x = scl*FX32_ONE;
				scale.y = scl*FX32_ONE;
				PkthlnClAct_SetScaleAffine(ptr->Ball[i].ShdwActPtr, &scale, CLACT_AFFINE_DOUBLE);
				PkthlnClAct_SetScaleAffine(ptr->Ball[i].BallActPtr, &scale, CLACT_AFFINE_DOUBLE);
				PkthlnClAct_SetScaleAffine(ptr->Ball[i].BreakActPtr, &scale, CLACT_AFFINE_DOUBLE);
			}
			//自分ボールの場合
			if (i/ENTRY_MAX == my_net_id){
				//ボールサイズが大きくなったらＳＥがなる
				if (ptr->BallSizeTemp[i%ENTRY_MAX] != ball_size){
					Snd_SePlay( SE_THROW_BALL_UP );		//ボール大きくなるＳＥ
					ptr->BallSizeTemp[i%ENTRY_MAX] = ball_size;
				}
			}
		}else{
			PkthlnClAct_SetActive(ptr->Ball[i].ShdwActPtr, 1, 0);	//不可視でセット
			PkthlnClAct_SetActive(ptr->Ball[i].BallActPtr, 1, 0);	//不可視でセット
			if (b_st == BALL_ST_BREAK){
				if(!ptr->Ball[i].BreakFlg){
					const VecFx32 *vec;
					//エフェクト検出フラグセット
					ptr->Ball[i].BreakFlg = 1;
					//玉の座標取得
					vec = PkthlnClAct_GetPos(ptr->Ball[i].BallActPtr);
					//粉砕アニメ座標セット
					PkthlnClAct_SetPos(ptr->Ball[i].BreakActPtr, vec);
					//アニメ開始
					PkthlnClAct_ChgAnm(ptr->Ball[i].BreakActPtr, 3);
					PkthlnClAct_SetActive(ptr->Ball[i].BreakActPtr, 1, 1);	//可視

					//自分のボールの場合
					if (i/ENTRY_MAX == my_net_id){
						Snd_SePlay( SE_THROW_BALL_HIT );		//ボール壊れＳＥ
						//ボール壊れたら、次弾撃てるので、投げるＳＥフラグ落とす
						ptr->ThrowSeFlg[i%ENTRY_MAX] = 0;
						//SE用テンポラリボールサイズをデフォルトに戻す
						ptr->BallSizeTemp[i%ENTRY_MAX] = 0;
					}
				}
			}
		}
	}//end for

	SortObj(ptr, my_net_id);

	//ラスト３秒
	PTFrame_DispLastCount(work, time*30);
}

//----------------------------------------------------------------------------
/**
 *	@brief	ポケモンをタッチしているかを判定する
 *
 *	@param	ptr		競技ポインタ
 *	@param	inNetID	ネットID
 *	@param	inX		X座標
 *	@param	inY		Y座標
 *	@param	outVec	変換結果座標格納バッファ
 *
 *	@return u8 タッチしたポケモンインデックス
 */
//-----------------------------------------------------------------------------
static u8 CheckPokeTouch(	PKTHLN_THROW_PTR ptr, const u8 inNetID,
							const u16 inX, const u16 inY, VecFx32 *outVec)
{
	int i;
	float x,z;
	VecFx32 vec;
	//タッチ座標を判定座標に変換
	ThClc_GetChkPosFromDspPos(inX, inY+(SUB_DISP_DISTANCE/FX32_ONE), &x, &z);

	vec.x = x*FX32_ONE;
	vec.z = z*FX32_ONE;
	vec.y = 0;

	//ネットIDごとに、座標回転を回転
	if (inNetID != COMM_PARENT_ID){
		MtxFx43 mtx;
		VecFx32 base, fix;

		//原点回転になるように、点を平行移動
		base = vec;
		base.x -= (33*FX32_ONE);
		base.z -= (33*FX32_ONE);
		//回転行列作成
		MTX_RotY43(&mtx, FX_SinIdx(0x4000*inNetID), FX_CosIdx(0x4000*inNetID));
		//ベクトルと行列を掛け合わせる
		MTX_MultVec43(&base, &mtx, &fix);
		//もとの位置に平行移動
		fix.x += (33*FX32_ONE);
		fix.z += (33*FX32_ONE);
		OS_Printf("fix = %d, %d\n",fix.x, fix.z);
		vec = fix;
	}

	OS_Printf("vec = %d,%d\n",vec.x/FX32_ONE, vec.z/FX32_ONE);

	//変換座標を格納
	*outVec = vec;

	for(i=inNetID*ENTRY_MAX;i<inNetID*ENTRY_MAX+ENTRY_MAX;i++){
		fx32 len;
		VecFx32 len_vec;
		VEC_Subtract(&ChkPokePos[i], &vec, &len_vec);
		OS_Printf("len_vec = %d,%d\n",len_vec.x/FX32_ONE, len_vec.z/FX32_ONE);
		len = VEC_Mag(&len_vec);
		OS_Printf("len = %d,%d\n",len, len/FX32_ONE);
		if (len <= POKE_TOUCH_RANGE){
			u8 poke_idx;
			OS_Printf("タッチヒット%d,%d\n",inNetID, i);
			poke_idx = i;
			return poke_idx;
		}
	}

	return THROW_EVENT_POKE_NUM_ALL;
}

//--------------------------------------------------------------------------------------------
/**
 * パラメータセット
 *
 * @param	work		ポケスロンワークポインタ
 * @param	*inData		パラメータ
 * @param	inNetID		ネットＩＤ
 * @param	inIdx		ポケモンエントリーインデックス0〜2
 * @param	*outPoke	パラメータ格納場所
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void SetPokeParam(	PKTHLN_PTR work, const THROW_PARAM *inData,
							const u8 inNetID, const u8 inIdx, THROW_POKE *outPoke)
{
	const POKE_SPEC *spec;
	spec = PTFrame_GetPokeSpec(work, inNetID, inIdx);

	OS_Printf("%d::tq2:pw:st = %d,%d,%d\n",
			inIdx,inData->Technique2[spec->Technique],inData->Power[spec->Power],inData->Damage[spec->Stamina]);

	outPoke->Technique2 = (float)inData->Technique2[spec->Technique]/10.0;
	outPoke->Power = (float)inData->Power[spec->Power]/10.0;
	outPoke->Technique = inData->Technique[spec->Technique];
	outPoke->Damage = (float)inData->Damage[spec->Stamina];

	outPoke->Point = 0;
	outPoke->StopTime = 0;
	outPoke->State = POKE_ST_NONE;

	outPoke->Hp = HP_MAX;
}

//----------レコードＢＭＰ---------------
//ＢＮＰウィンドウデータ
static const BMPWIN_DAT RecordBmpData = {
		REC_BG, WIN_REC_PX, WIN_REC_PY,
		WIN_REC_SX, WIN_REC_SY, REC_FONT_PAL, WIN_REC_CGX
};

static const BMPWIN_DAT NameBmpData[] = {
	{
		NAME_BG, WIN_NAME1_PX, WIN_NAME1_PY,
		WIN_NAME_SX, WIN_NAME_SY, NAME_FONT_PAL, WIN_NAME1_CGX
	},
	{
		NAME_BG, WIN_NAME2_PX, WIN_NAME2_PY,
		WIN_NAME_SX, WIN_NAME_SY, NAME_FONT_PAL, WIN_NAME2_CGX
	},
	{
		NAME_BG, WIN_NAME3_PX, WIN_NAME3_PY,
		WIN_NAME_SX, WIN_NAME_SY, NAME_FONT_PAL, WIN_NAME3_CGX
	},
};

//--------------------------------------------------------------------------------------------
/**
 * BMPウィンドウ追加
 *
 * @param 	ptr			コントローラポインタ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void CreateBmpWin( PKTHLN_THROW_PTR ptr )
{
	int i;
	const BMPWIN_DAT * dat = &RecordBmpData;
	const BMPWIN_DAT * name_dat = NameBmpData;

	GF_BGL_BmpWinAddEx( ptr->bgl, &ptr->Win, dat );
	//先頭キャラをクリア（スクリーンクリアされてるところは、このキャラで埋まる）
	GF_BGL_CharFill( ptr->bgl, REC_BG, 0, 1, 0 );
	GF_BGL_BmpWinDataFill( &ptr->Win, 0 );

	for(i=0;i<ENTRY_MEMBER_NUM_MAX-1;i++){
		GF_BGL_BmpWinAddEx( ptr->bgl, &ptr->NameWin[i], &name_dat[i] );
		GF_BGL_BmpWinDataFill( &ptr->NameWin[i], 0 );
	}
	//先頭キャラをクリア（スクリーンクリアされてるところは、このキャラで埋まる）
	GF_BGL_CharFill( ptr->bgl, NAME_BG, 0, 1, 0 );

	//システム用フォントパレット転送
	SystemFontPaletteLoad(PALTYPE_MAIN_BG, REC_FONT_PAL*32, ptr->HeapID);
}

//----------------------------------------------------------------------------
/**
 *	@brief		レコード文字列展開
 *
 *	@param	ptr			コントローラポインタ
 *	@param	inRecord	記録
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void SetRecordStr(PKTHLN_THROW_PTR ptr, const int inRecord)
{
	WORDSET *word;
	STRBUF * str;
	MSGDATA_MANAGER *msgman;
	int integer;

	GF_BGL_BmpWinDataFill( &ptr->Win, 0);

	//整数部分
	integer = inRecord;

	msgman = MSGMAN_Create(MSGMAN_TYPE_DIRECT, ARC_MSG, NARC_msg_pokethlon_dat, ptr->HeapID);
    word = WORDSET_Create(ptr->HeapID);
	WORDSET_RegisterNumber(word, 0, integer, 3,
				NUMBER_DISPTYPE_LEFT,NUMBER_CODETYPE_DEFAULT);

    str = MSGDAT_UTIL_AllocExpandString(word, msgman, msg_pkthln_new_record09, ptr->HeapID);

	GF_STR_PrintColor( 	&ptr->Win, FONT_TOUCH, str,
					0, 0, MSG_NO_PUT, COL_N_WHITE, NULL );
	STRBUF_Delete(str);//<一括表示なので、メモリをここで消してもOK
	WORDSET_Delete( word );
	MSGMAN_Delete( msgman );

	GF_BGL_BmpWinOn(&ptr->Win);
}

//----------------------------------------------------------------------------
/**
 *	@brief	ポケモン動作
 *
 *	@param	work		ポケスロンワークポインタ
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void MovePoke(PKTHLN_PTR work)
{
	int i;
	PKTHLN_THROW_PTR ptr = PTFrame_GetEventWorkPtr(work);
	for(i=0;i<THROW_EVENT_POKE_NUM_ALL;i++){
		//動作不能時間のデクリメント
		if (ptr->Poke[i].StopTime > 0){
			ptr->Poke[i].StopTime--;
		}
		//HPの回復
		if (ptr->Poke[i].Hp < HP_MAX){
			ptr->Poke[i].Hp++;
		}
		//行動不能ならば、気絶ステートにする
		if (ptr->Poke[i].StopTime > 0){
			ptr->Poke[i].State = POKE_ST_PANIC;		//気絶
		}else if(ptr->Poke[i].Hp <= FATIGUE_ST_VAL){
			ptr->Poke[i].State = POKE_ST_FATIGUE;	//疲労
		}else{
			ptr->Poke[i].State = POKE_ST_NONE;
		}
	}
#if 0
#ifdef PM_DEBUG
	if(sys.cont & PAD_KEY_DOWN){
		ptr->Poke[0].State = POKE_ST_PANIC;
		ptr->Poke[1].State = POKE_ST_PANIC;
		ptr->Poke[2].State = POKE_ST_PANIC;
	}
	if (sys.cont & PAD_KEY_RIGHT){
		ptr->Poke[3].State = POKE_ST_PANIC;
		ptr->Poke[4].State = POKE_ST_PANIC;
		ptr->Poke[5].State = POKE_ST_PANIC;
	}
	if (sys.cont & PAD_KEY_UP){
		ptr->Poke[6].State = POKE_ST_PANIC;
		ptr->Poke[7].State = POKE_ST_PANIC;
		ptr->Poke[8].State = POKE_ST_PANIC;
	}
	if (sys.cont & PAD_KEY_LEFT){
		ptr->Poke[9].State = POKE_ST_PANIC;
		ptr->Poke[10].State = POKE_ST_PANIC;
		ptr->Poke[11].State = POKE_ST_PANIC;
	}
#endif
#endif
}

//----------------------------------------------------------------------------
/**
 *	@brief	ボール動作
 *
 *	@param	work		ポケスロンワークポインタ
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void MoveBall(PKTHLN_PTR work)
{
#if 1
	int i;
	PKTHLN_THROW_PTR ptr = PTFrame_GetEventWorkPtr(work);

	for(i=0;i<THROW_EVENT_POKE_NUM_ALL;i++){
		u8 none = 0;
		if (ptr->Ball[i].State == BALL_ST_MOVE){
			//ボール移動
			VEC_MultAdd(1*FX32_ONE, &ptr->Ball[i].Dir, &ptr->Ball[i].Pos, &ptr->Ball[i].Pos);
		}else if(ptr->Ball[i].State == BALL_ST_BREAK){
			//粉砕後硬直時間
			ptr->Ball[i].BreakWait++;
			if (ptr->Ball[i].BreakWait >= BREAK_WAIT){
				ptr->Ball[i].BreakWait = 0;
				ptr->Ball[i].State = BALL_ST_NONE;
			}
		}

		//判定空間内外判定
		if ( (ptr->Ball[i].Pos.x < FX32_ONE)||(ptr->Ball[i].Pos.x>64*FX32_ONE)||
				(ptr->Ball[i].Pos.z < FX32_ONE)||(ptr->Ball[i].Pos.z>64*FX32_ONE) ){
			//空間外
			none = 1;
		}

		if (none){
			ptr->Ball[i].State = BALL_ST_NONE;
			ptr->Ball[i].Dir.x = 0;
			ptr->Ball[i].Dir.z = 0;
			ptr->Ball[i].Dir.y = 0;
			ptr->Ball[i].ShotPos.x = 0;
			ptr->Ball[i].ShotPos.z = 0;
			ptr->Ball[i].ShotPos.y = 0;
		}
	}
#endif
#if 0
	fx32 len,my_len;
	VecFx32 len_vec,vec;
	VecFx32 dir;
	u8 none = 0;
	PKTHLN_THROW_PTR ptr = PTFrame_GetEventWorkPtr(work);

	if (ptr->Ball[poke_no].State == BALL_ST_NONE){
		ptr->Ball[poke_no].State = BALL_ST_MOVE;
	}

	if (ptr->Ball[poke_no].State == BALL_ST_MOVE){
		//方向ベクトル決定
		VEC_Subtract(&target_pos, &start_pos, &len_vec);
		VEC_Normalize(&len_vec, &dir);
		//ボール移動
		VEC_MultAdd(1*FX32_ONE, &dir, &ptr->Ball[poke_no].Pos, &ptr->Ball[poke_no].Pos);
		//移動フレームカウンタ加算
		ptr->Ball[poke_no].Frame++;

		//目的地到着判定
		VEC_Subtract(&ptr->Ball[poke_no].Pos, &start_pos, &vec);
		len = VEC_Mag(&len_vec);
		my_len = VEC_Mag(&vec);
		if(my_len >= len){
			//到着。
			ptr->Ball[poke_no].Frame=0;
			ptr->Ball[poke_no].State = BALL_ST_BREAK;
			shot_count++;
			//すべての場所に発射したか？
			if(shot_count<9){
				//まだ。ボールの位置を戻し、目的地を決定する
				ptr->Ball[poke_no].Pos = start_pos;
				t_poke_no = (t_poke_no+1)%THROW_EVENT_POKE_NUM_ALL;
				target_pos = ChkPokePos[t_poke_no];
			}else{
				//全部発射。発射ポイントを変える
				shot_count = 0;
				poke_no = (poke_no+1)%THROW_EVENT_POKE_NUM_ALL;
				start_pos = ChkPokePos[poke_no];
				t_poke_no = (poke_no/ENTRY_MAX)*ENTRY_MAX+3;
				t_poke_no %= THROW_EVENT_POKE_NUM_ALL;
				target_pos = ChkPokePos[t_poke_no];
				ptr->Ball[poke_no].Pos = start_pos;
			}
		}
	}

	else if(ptr->Ball[poke_no].State == BALL_ST_BREAK){
		//粉砕後硬直時間
		ptr->Ball[poke_no].BreakWait++;
		if (ptr->Ball[poke_no].BreakWait >= BREAK_WAIT){
			ptr->Ball[poke_no].BreakWait = 0;
			ptr->Ball[poke_no].State = BALL_ST_NONE;
		}
	}

	//判定空間内外判定
	if ( (ptr->Ball[poke_no].Pos.x < FX32_ONE)||(ptr->Ball[poke_no].Pos.x>64*FX32_ONE)||
			(ptr->Ball[poke_no].Pos.z < FX32_ONE)||(ptr->Ball[poke_no].Pos.z>64*FX32_ONE) ){
		//空間外
		none = 1;
	}
	//玉の高さ
	{
		int val;
		val = ptr->Ball[poke_no].Frame-30;
		ptr->Ball[poke_no].YVal = (val*val)/240;
		if (ptr->Ball[poke_no].YVal >= 4){
			ptr->Ball[poke_no].YVal = 0;
			none = 1;
		}
	}
	if (none){
		ptr->Ball[poke_no].State = BALL_ST_NONE;
		ptr->Ball[poke_no].Dir.x = 0;
		ptr->Ball[poke_no].Dir.z = 0;
		ptr->Ball[poke_no].Dir.y = 0;
		ptr->Ball[poke_no].ShotPos.x = 0;
		ptr->Ball[poke_no].ShotPos.z = 0;
		ptr->Ball[poke_no].ShotPos.y = 0;
	}
#endif
}

//----------------------------------------------------------------------------
/**
 *	@brief	ボールとポケモンの当たり判定
 *
 *	@param	work		ポケスロンワークポインタ
 *	@param	ptr			競技ポインタ
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void HitCheckPoke(PKTHLN_PTR work, PKTHLN_THROW_PTR ptr)
{
	int i,j;
	for(i=0;i<THROW_EVENT_POKE_NUM_ALL;i++){
		//ポケヒットクリア
		ptr->Poke[i].Hit = 0;
		for(j=0;j<THROW_EVENT_POKE_NUM_ALL;j++){
			//玉が存在しなければ処理をスルー
			if (ptr->Ball[j].State != BALL_ST_MOVE){
				continue;
			}
			//玉が自分チームの玉かを判定
			if ( (j/ENTRY_MAX) == (i/ENTRY_MAX) ){
				continue;
			}
			//ヒット判定
			{
				VecFx32 vec;
				fx32 len;
				VEC_Subtract(&ChkPokePos[i], &ptr->Ball[j].Pos, &vec);
				len = VEC_Mag(&vec);
				if (len < (BALL_RANGE+POKE_RANGE)*FX32_ONE ){
					OS_Printf("ヒット%d,%d\n",i,j);
					ptr->Ball[j].State = BALL_ST_BREAK;

					//アクションポイント加算「得点回数」
					PTFrame_AddActionPoint(	work, j/ENTRY_MAX, j%ENTRY_MAX, ADD_TYPE_GET, 1 );

					//得点加算
					ptr->Poke[j].Point++;
					if (ptr->Poke[j].Point > POINT_MAX){
						ptr->Poke[j].Point = POINT_MAX;
					}
					//得点取得フラグ成立
					ptr->Ball[j].PointGet = 1;

					//ポケヒット
					ptr->Poke[i].Hit = 1;

					//HP減少
					{
						u8 stop_time;
						float cof;
						float flt_len;
						int dif;
						//玉係数算出
						switch( ptr->Ball[j].Size ){
						case 0:
							cof = 1.0;
							break;
						case 1:
							cof = 20.0;
							break;
						case 2:
							cof = 50.0;
							break;
						case 3:
							cof = 100.0;
							break;
						default:
							GF_ASSERT(0);
							cof = 1.0;
						}
						//サイズクリア
						ptr->Ball[j].Size = 0;
						//レベルクリア
						ptr->Ball[j].Level = 0;

						flt_len = VEC_Mag(&ptr->Ball[j].Dir)/FX32_ONE;
						dif = (flt_len * cof * ptr->Poke[j].Power * ptr->Poke[i].Damage);
						GF_ASSERT(dif>=0);
						ptr->Poke[i].Hp = ptr->Poke[i].Hp - dif - CMN_DAMAGE;
						if ( ptr->Poke[i].Hp < 0 ){
							ptr->Poke[i].Hp = 0;
						}

						//行動不能時間算出
						stop_time = (HP_MAX-ptr->Poke[i].Hp);
						if (ptr->Poke[i].StopTime == 0){
							if (stop_time > STOP_TIME_MIN){
								ptr->Poke[i].StopTime = stop_time;
								//アクションポイント加算「失敗回数」	<<気絶開始
								PTFrame_AddActionPoint(	work, i/ENTRY_MAX, i%ENTRY_MAX, ADD_TYPE_FAIL, 1 );
							}
						}else{
							ptr->Poke[i].StopTime += stop_time;
							//アクションポイント加算「失敗回数」	<<気絶中の累積
							PTFrame_AddActionPoint(	work, i/ENTRY_MAX, i%ENTRY_MAX, ADD_TYPE_FAIL, 1 );
						}
					}

				}
			}
		}
	}
}

//----------------------------------------------------------------------------
/**
 *	@brief	ボールのヒットチェック
 *
 *	@param	ptr			競技ポインタ
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void HitCheckBall(PKTHLN_THROW_PTR ptr)
{
	u8 hit_ball[THROW_EVENT_POKE_NUM_ALL];
	int i,j;

	//初期化
	for(i=0;i<BALL_NUM_MAX;i++){
		hit_ball[i] = 0;
	}

	for(i=0;i<BALL_NUM_MAX;i++){
		//玉が存在しなければ処理をスルー
		if ( (ptr->Ball[i].State != BALL_ST_MOVE)&&
				(ptr->Ball[i].State != BALL_ST_SET) ){
			continue;
		}
		for(j=0;j<BALL_NUM_MAX;j++){
			//自分同士は処理しない
			if (i==j){
				continue;
			}
			//玉が存在しなければ処理をスルー
			if ( (ptr->Ball[j].State != BALL_ST_MOVE)&&
					(ptr->Ball[j].State != BALL_ST_SET) ){
				continue;
			}
			//ヒット判定
			{
				VecFx32 vec;
				fx32 len;
				VEC_Subtract(&ptr->Ball[i].Pos, &ptr->Ball[j].Pos, &vec);
				len = VEC_Mag(&vec);
				if (len < (BALL_RANGE*2)*FX32_ONE ){
					OS_Printf("ボール同士ヒット%d,%d\n",i,j);
					hit_ball[i] = 1;
					hit_ball[j] = 1;

				}
			}
		}
	}

	for(i=0;i<THROW_EVENT_POKE_NUM_ALL;i++){
		if (hit_ball[i]){
			ptr->Ball[i].State = BALL_ST_BREAK;
			//サイズクリア
			ptr->Ball[i].Size = 0;
			//レベルクリア
			ptr->Ball[i].Level = 0;
		}
	}
}

//----------------------------------------------------------------------------
/**
 *	@brief	プレーヤー名プリント
 *
 *	@param	ptr			競技ポインタ
 *	@param	work		ポケスロンワークポインタ
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void WriteName(PKTHLN_THROW_PTR ptr, PKTHLN_PTR work)
{
	int i;
	u8 net_id;
	net_id = PTFrameGetCurrentID(work);
	for (i=0; i<ENTRY_MEMBER_NUM_MAX-1; i++){
		STRBUF *name_buf;
		u8 idx;
		idx = (net_id+1+i)%ENTRY_MEMBER_NUM_MAX;
		//マイステータスにアクセスして名前取得
		name_buf = MyStatus_CreateNameString(
					PTFrame_GetMyStatus(work, idx),
					ptr->HeapID);
		GF_STR_PrintColor( 	&ptr->NameWin[i], FONT_SYSTEM, name_buf,
					0, 0, MSG_NO_PUT, COL_N_WHITE, NULL );
		STRBUF_Delete(name_buf);
		GF_BGL_BmpWinOn(&ptr->NameWin[i]);
	}
}

//----------------------------------------------------------------------------
/**
 *	@brief	時間表示
 *
 *	@param	ptr			競技ポインタ
 *	@param	inTime		時間
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void DispTime(PKTHLN_THROW_PTR ptr, const u16 inTime)
{
	u8 sec,sec_t,sec_o;
	//秒計算
	sec = inTime;
	sec_t = sec / 10;
	sec_o = sec % 10;
	CLACT_AnmChg(ptr->TimeActPtr[0], sec_t+1);
	CLACT_AnmChg(ptr->TimeActPtr[1], sec_o+1);
}

//--------------------------------------------------------------------------------------------
/**
 * レコードコールバック関数
 *
 * @param	work		ポケスロンワークポインタ
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void RecCallBack(PKTHLN_PTR work)
{
	COMM_EVENT_COMMON_DATA * data;
	THROW_PARENT_DATA *parent;
	PKTHLN_THROW_PTR ptr;

	data = PTFrame_GetEvtComCmnData(work);
	parent = PKTHLN_CommPack_GetData(&data->ReciveShareData);
	ptr = PTFrame_GetEventWorkPtr(work);

	//ニューレコード用にレコードをセット
	{
		u16 point;
		u8 my_net_id;

		my_net_id = PTFrameGetCurrentID(work);
		point = parent->Prm[my_net_id] & 0x3ff;	//10ビットマスク
		if (point > POINT_MAX){
			point = POINT_MAX;
		}
		//フレームワークにニューレコードチェック用のレコード値をセット
		PTFrame_SetCheckRecord(work, point);
		SetRecordStr(ptr, point);
	}
}

//--------------------------------------------------------------------------------------------
/**
 * ソート用比較関数
 * ※NitroSDKのソート関数のコールバックは自分自身の比較もしているようだ
 *
 * @param	elem1		要素1
 * @param	elem2		要素2
 * @return	s32			ソート結果
 */
//--------------------------------------------------------------------------------------------
static s32 CompFunc(void *elem1, void *elem2)
{
	s32 ret;
	SORT_WORK * obj1 = elem1;
	SORT_WORK * obj2 = elem2;
	u8 net_id;

	net_id = obj1->NetID;
	if (obj1->Y > obj2->Y){		//要素1の方がY値が高い場合は要素1を前に
		ret = -1;		//要素1が前
	}else if( obj1->Y < obj2->Y ){	//要素2の方がY値が高い場合は要素2を前に
		ret = 1;		//要素2が後
	}else{	//Yの値が同じ場合、ボールに割り振られたインデックスから参照されるテーブルの値の小さい方を優先するようにする
		if ( DefBallPri[net_id][obj1->Idx] < DefBallPri[net_id][obj2->Idx] ){
			ret = -1;
		}else if( DefBallPri[net_id][obj1->Idx] > DefBallPri[net_id][obj2->Idx] ){
			ret = 1;
		}else {
			//※NitroSDKのソート関数のコールバックは自分自身の比較もしているようなので、ここにアサートがあるととまってしまう
			//GF_ASSERT_MSG(0,"%d_%d\n",ball1->Idx, ball2->Idx);
			ret = 0;
		}
	}
	return ret;
}

//--------------------------------------------------------------------------------------------
/**
 * 表示ソート
 *
 * @param	ptr			競技ポインタ
 * @param	inNetID		ネットID
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void SortObj(PKTHLN_THROW_PTR ptr, const u8 inNetID)
{
	u8 i;
	u32 size;
	SORT_WORK sort_work[SORT_NUM_MAX];
	for (i=0;i<SORT_NUM_MAX;i++){
		const VecFx32 *vec = PkthlnClAct_GetPos(ptr->Ball[i].ShdwActPtr);
		sort_work[i].Idx = ptr->Ball[i].OrgIdx;
		sort_work[i].Y = vec->y;
		sort_work[i].NetID = inNetID;

	}
	size = sizeof(SORT_WORK);

	MATH_QSort( sort_work,
			    SORT_NUM_MAX,
				size,
				CompFunc,
				ptr->SortBuf );

	for (i=0;i<SORT_NUM_MAX;i++){
		u8 idx;
		idx = sort_work[i].Idx;
		PkthlnClAct_SetPriority(ptr->Ball[idx].BallActPtr, PRI_BALL+i);
		PkthlnClAct_SetPriority(ptr->Ball[idx].BreakActPtr, PRI_BREAK+i);
///		OS_Printf("orgidx = %d\n",sort_work[i].Idx);
	}
}
